From 9337f8f081ca2db0a6a3e1029187e0b073fb3a37 Mon Sep 17 00:00:00 2001 From: envestcc Date: Thu, 21 Aug 2025 09:01:54 +0800 Subject: [PATCH 01/26] systemcontracts for erigon --- systemcontracts/GenericStorage.sol | 230 ++++++++ systemcontracts/NamespaceStorage.sol | 386 +++++++++++++ systemcontracts/generic_storage.go | 439 +++++++++++++++ systemcontracts/generic_storage_abi.go | 301 ++++++++++ systemcontracts/namespace_storage.go | 680 +++++++++++++++++++++++ systemcontracts/namespace_storage_abi.go | 506 +++++++++++++++++ systemcontracts/systemcontracts.go | 141 +++++ 7 files changed, 2683 insertions(+) create mode 100644 systemcontracts/GenericStorage.sol create mode 100644 systemcontracts/NamespaceStorage.sol create mode 100644 systemcontracts/generic_storage.go create mode 100644 systemcontracts/generic_storage_abi.go create mode 100644 systemcontracts/namespace_storage.go create mode 100644 systemcontracts/namespace_storage_abi.go create mode 100644 systemcontracts/systemcontracts.go diff --git a/systemcontracts/GenericStorage.sol b/systemcontracts/GenericStorage.sol new file mode 100644 index 0000000000..33e586c3e2 --- /dev/null +++ b/systemcontracts/GenericStorage.sol @@ -0,0 +1,230 @@ +// SPDX-License-Identifier: Apache-2.0 +pragma solidity ^0.8.0; + +/** + * @title GenericStorage + * @dev Generic storage contract for key-value data with flexible value structure + * This contract provides a universal storage solution with support for: + * - Basic CRUD operations (put, get, delete) + * - Batch operations (batchGet) + * - Listing all stored data + * - Flexible value structure with immutable and mutable fields + */ +contract GenericStorage { + + /** + * @dev Generic value structure with multiple fields for flexibility + * @param primaryData Primary data field for main content + * @param secondaryData Secondary data field for additional content + * @param auxiliaryData Additional data field for extended use cases + */ + struct GenericValue { + bytes primaryData; // Primary data field + bytes secondaryData; // Secondary data field + bytes auxiliaryData; // Additional data field for flexibility + } + + // Main storage mapping + mapping(bytes => GenericValue) private storage_; + + // Array to keep track of all keys for listing functionality + bytes[] private keys_; + + // Mapping to check if a key exists (for efficient existence checks) + mapping(bytes => bool) private keyExists_; + + // Events + event DataStored(bytes indexed key); + event DataDeleted(bytes indexed key); + event BatchDataRetrieved(uint256 keyCount); + event StorageCleared(); + + /** + * @dev Store data with a given key + * @param key The storage key + * @param value The GenericValue struct to store + */ + function put( + bytes memory key, + GenericValue memory value + ) external { + require(key.length > 0, "Key cannot be empty"); + + // If key doesn't exist, add it to keys array + if (!keyExists_[key]) { + keys_.push(key); + keyExists_[key] = true; + } + + // Store the value + storage_[key] = value; + + emit DataStored(key); + } + + /** + * @dev Delete data by key + * @param key The storage key to delete + */ + function remove(bytes memory key) external { + require(keyExists_[key], "Key does not exist"); + + // Remove from storage + delete storage_[key]; + keyExists_[key] = false; + + // Remove from keys array + for (uint256 i = 0; i < keys_.length; i++) { + if (keccak256(keys_[i]) == keccak256(key)) { + // Move last element to current position and pop + keys_[i] = keys_[keys_.length - 1]; + keys_.pop(); + break; + } + } + + emit DataDeleted(key); + } + + /** + * @dev Get data by key + * @param key The storage key + * @return value The stored GenericValue struct + * @return keyExists Whether the key exists + */ + function get(bytes memory key) external view returns (GenericValue memory value, bool keyExists) { + keyExists = keyExists_[key]; + if (keyExists) { + value = storage_[key]; + } + return (value, keyExists); + } + + /** + * @dev Batch get data by multiple keys + * @param keyList Array of keys to retrieve + * @return values Array of GenericValue structs + * @return existsFlags Array indicating which keys exist + */ + function batchGet(bytes[] memory keyList) external view returns ( + GenericValue[] memory values, + bool[] memory existsFlags + ) { + values = new GenericValue[](keyList.length); + existsFlags = new bool[](keyList.length); + + for (uint256 i = 0; i < keyList.length; i++) { + existsFlags[i] = keyExists_[keyList[i]]; + if (existsFlags[i]) { + values[i] = storage_[keyList[i]]; + } + } + + return (values, existsFlags); + } + + /** + * @dev List all stored data with pagination + * @param offset Starting index for pagination + * @param limit Maximum number of items to return + * @return keyList Array of keys + * @return values Array of corresponding GenericValue structs + * @return total Total number of stored items + */ + function list(uint256 offset, uint256 limit) external view returns ( + bytes[] memory keyList, + GenericValue[] memory values, + uint256 total + ) { + total = keys_.length; + + // Handle edge cases for pagination + if (offset >= total) { + keyList = new bytes[](0); + values = new GenericValue[](0); + return (keyList, values, total); + } + + // Calculate actual limit + uint256 remainingItems = total - offset; + uint256 actualLimit = limit > remainingItems ? remainingItems : limit; + + // Create result arrays + keyList = new bytes[](actualLimit); + values = new GenericValue[](actualLimit); + + // Fill result arrays + for (uint256 i = 0; i < actualLimit; i++) { + bytes memory key = keys_[offset + i]; + keyList[i] = key; + values[i] = storage_[key]; + } + + return (keyList, values, total); + } + + /** + * @dev List all keys only (lightweight version) + * @param offset Starting index for pagination + * @param limit Maximum number of keys to return + * @return keyList Array of keys + * @return total Total number of stored items + */ + function listKeys(uint256 offset, uint256 limit) external view returns ( + bytes[] memory keyList, + uint256 total + ) { + total = keys_.length; + + if (offset >= total) { + keyList = new bytes[](0); + return (keyList, total); + } + + uint256 remainingItems = total - offset; + uint256 actualLimit = limit > remainingItems ? remainingItems : limit; + + keyList = new bytes[](actualLimit); + + for (uint256 i = 0; i < actualLimit; i++) { + keyList[i] = keys_[offset + i]; + } + + return (keyList, total); + } + + /** + * @dev Check if a key exists + * @param key The storage key to check + * @return keyExists Whether the key exists + */ + function exists(bytes memory key) external view returns (bool keyExists) { + return keyExists_[key]; + } + + /** + * @dev Get total number of stored items + * @return totalCount Total number of items + */ + function count() external view returns (uint256 totalCount) { + return keys_.length; + } + + /** + * @dev Clear all stored data (emergency function) + * Note: This function should be carefully protected in production + */ + function clear() external { + // Clear all mappings and arrays + for (uint256 i = 0; i < keys_.length; i++) { + bytes memory key = keys_[i]; + delete storage_[key]; + keyExists_[key] = false; + } + + // Clear keys array + delete keys_; + + emit StorageCleared(); + } +} \ No newline at end of file diff --git a/systemcontracts/NamespaceStorage.sol b/systemcontracts/NamespaceStorage.sol new file mode 100644 index 0000000000..1ae024cf80 --- /dev/null +++ b/systemcontracts/NamespaceStorage.sol @@ -0,0 +1,386 @@ +// SPDX-License-Identifier: Apache-2.0 +pragma solidity ^0.8.0; + +/** + * @title NamespaceStorage + * @dev Namespace-aware storage contract for key-value data with flexible value structure + * This contract extends the GenericStorage concept with namespace support for data isolation + */ +contract NamespaceStorage { + + /** + * @dev Generic value structure with multiple fields for flexibility + * @param primaryData Primary data field for main content + * @param secondaryData Secondary data field for additional content + * @param auxiliaryData Additional data field for extended use cases + */ + struct GenericValue { + bytes primaryData; // Primary data field + bytes secondaryData; // Secondary data field + bytes auxiliaryData; // Additional data field for flexibility + } + + // Nested mapping: namespace => key => value + mapping(string => mapping(bytes => GenericValue)) private namespaceStorage_; + + // Track keys for each namespace + mapping(string => bytes[]) private namespaceKeys_; + + // Track if a key exists in a namespace + mapping(string => mapping(bytes => bool)) private keyExists_; + + // Track all namespaces + string[] private namespaces_; + mapping(string => bool) private namespaceExists_; + + // Events for tracking operations + event DataStored(string indexed namespace, bytes indexed key); + event DataDeleted(string indexed namespace, bytes indexed key); + event BatchDataRetrieved(string indexed namespace, uint256 keyCount); + event NamespaceCleared(string indexed namespace); + event AllDataCleared(); + + /** + * @dev Store data with a given namespace and key + * @param namespace The namespace for data isolation + * @param key The storage key within the namespace + * @param value The GenericValue struct to store + */ + function put( + string memory namespace, + bytes memory key, + GenericValue memory value + ) external { + require(bytes(namespace).length > 0, "Namespace cannot be empty"); + require(key.length > 0, "Key cannot be empty"); + + // Add namespace if it doesn't exist + if (!namespaceExists_[namespace]) { + namespaces_.push(namespace); + namespaceExists_[namespace] = true; + } + + // If key doesn't exist in this namespace, add it to keys array + if (!keyExists_[namespace][key]) { + namespaceKeys_[namespace].push(key); + keyExists_[namespace][key] = true; + } + + // Store the value + namespaceStorage_[namespace][key] = value; + + emit DataStored(namespace, key); + } + + /** + * @dev Get data by namespace and key + * @param namespace The namespace containing the key + * @param key The storage key + * @return value The stored GenericValue struct + * @return keyExists Whether the key exists in the namespace + */ + function get(string memory namespace, bytes memory key) external view returns ( + GenericValue memory value, + bool keyExists + ) { + keyExists = keyExists_[namespace][key]; + if (keyExists) { + value = namespaceStorage_[namespace][key]; + } + return (value, keyExists); + } + + /** + * @dev Delete data by namespace and key + * @param namespace The namespace containing the key + * @param key The storage key to delete + */ + function remove(string memory namespace, bytes memory key) external { + require(namespaceExists_[namespace], "Namespace does not exist"); + require(keyExists_[namespace][key], "Key does not exist in namespace"); + + // Remove from storage + delete namespaceStorage_[namespace][key]; + keyExists_[namespace][key] = false; + + // Remove from keys array + bytes[] storage keys = namespaceKeys_[namespace]; + for (uint256 i = 0; i < keys.length; i++) { + if (keccak256(keys[i]) == keccak256(key)) { + // Move last element to current position and pop + keys[i] = keys[keys.length - 1]; + keys.pop(); + break; + } + } + + emit DataDeleted(namespace, key); + } + + /** + * @dev Batch get data by multiple keys within a namespace + * @param namespace The namespace to query + * @param keyList Array of keys to retrieve + * @return values Array of GenericValue structs + * @return existsFlags Array indicating which keys exist + */ + function batchGet(string memory namespace, bytes[] memory keyList) external view returns ( + GenericValue[] memory values, + bool[] memory existsFlags + ) { + values = new GenericValue[](keyList.length); + existsFlags = new bool[](keyList.length); + + for (uint256 i = 0; i < keyList.length; i++) { + existsFlags[i] = keyExists_[namespace][keyList[i]]; + if (existsFlags[i]) { + values[i] = namespaceStorage_[namespace][keyList[i]]; + } + } + + return (values, existsFlags); + } + + /** + * @dev Batch put multiple key-value pairs in the same namespace + * @param namespace The namespace for all data + * @param keys Array of keys to store + * @param values Array of values to store + */ + function batchPut( + string memory namespace, + bytes[] memory keys, + GenericValue[] memory values + ) external { + require(keys.length == values.length, "Keys and values arrays must have same length"); + require(bytes(namespace).length > 0, "Namespace cannot be empty"); + + // Add namespace if it doesn't exist + if (!namespaceExists_[namespace]) { + namespaces_.push(namespace); + namespaceExists_[namespace] = true; + } + + for (uint256 i = 0; i < keys.length; i++) { + require(keys[i].length > 0, "Key cannot be empty"); + + // If key doesn't exist in this namespace, add it to keys array + if (!keyExists_[namespace][keys[i]]) { + namespaceKeys_[namespace].push(keys[i]); + keyExists_[namespace][keys[i]] = true; + } + + // Store the value + namespaceStorage_[namespace][keys[i]] = values[i]; + + emit DataStored(namespace, keys[i]); + } + } + + /** + * @dev List all stored data in a namespace with pagination + * @param namespace The namespace to list + * @param offset Starting index for pagination + * @param limit Maximum number of items to return + * @return keyList Array of keys + * @return values Array of corresponding GenericValue structs + * @return total Total number of stored items in the namespace + */ + function list(string memory namespace, uint256 offset, uint256 limit) external view returns ( + bytes[] memory keyList, + GenericValue[] memory values, + uint256 total + ) { + bytes[] storage keys = namespaceKeys_[namespace]; + total = keys.length; + + // Handle edge cases for pagination + if (offset >= total) { + keyList = new bytes[](0); + values = new GenericValue[](0); + return (keyList, values, total); + } + + // Calculate actual limit + uint256 remainingItems = total - offset; + uint256 actualLimit = limit > remainingItems ? remainingItems : limit; + + // Create result arrays + keyList = new bytes[](actualLimit); + values = new GenericValue[](actualLimit); + + // Fill result arrays + for (uint256 i = 0; i < actualLimit; i++) { + bytes memory key = keys[offset + i]; + keyList[i] = key; + values[i] = namespaceStorage_[namespace][key]; + } + + return (keyList, values, total); + } + + /** + * @dev List all keys in a namespace (lightweight version) + * @param namespace The namespace to list + * @param offset Starting index for pagination + * @param limit Maximum number of keys to return + * @return keyList Array of keys + * @return total Total number of stored items in the namespace + */ + function listKeys(string memory namespace, uint256 offset, uint256 limit) external view returns ( + bytes[] memory keyList, + uint256 total + ) { + bytes[] storage keys = namespaceKeys_[namespace]; + total = keys.length; + + if (offset >= total) { + keyList = new bytes[](0); + return (keyList, total); + } + + uint256 remainingItems = total - offset; + uint256 actualLimit = limit > remainingItems ? remainingItems : limit; + + keyList = new bytes[](actualLimit); + + for (uint256 i = 0; i < actualLimit; i++) { + keyList[i] = keys[offset + i]; + } + + return (keyList, total); + } + + /** + * @dev List all namespaces with pagination + * @param offset Starting index for pagination + * @param limit Maximum number of namespaces to return + * @return namespaceList Array of namespace names + * @return counts Array of item counts for each namespace + * @return total Total number of namespaces + */ + function listNamespaces(uint256 offset, uint256 limit) external view returns ( + string[] memory namespaceList, + uint256[] memory counts, + uint256 total + ) { + total = namespaces_.length; + + if (offset >= total) { + namespaceList = new string[](0); + counts = new uint256[](0); + return (namespaceList, counts, total); + } + + uint256 remainingItems = total - offset; + uint256 actualLimit = limit > remainingItems ? remainingItems : limit; + + namespaceList = new string[](actualLimit); + counts = new uint256[](actualLimit); + + for (uint256 i = 0; i < actualLimit; i++) { + string memory ns = namespaces_[offset + i]; + namespaceList[i] = ns; + counts[i] = namespaceKeys_[ns].length; + } + + return (namespaceList, counts, total); + } + + /** + * @dev Check if a key exists in a namespace + * @param namespace The namespace to check + * @param key The storage key to check + * @return keyExists Whether the key exists in the namespace + */ + function exists(string memory namespace, bytes memory key) external view returns (bool keyExists) { + return keyExists_[namespace][key]; + } + + /** + * @dev Check if a namespace exists + * @param namespace The namespace to check + * @return nsExists Whether the namespace exists + */ + function hasNamespace(string memory namespace) external view returns (bool nsExists) { + return namespaceExists_[namespace]; + } + + /** + * @dev Get total number of stored items in a namespace + * @param namespace The namespace to count + * @return itemCount Total number of items in the namespace + */ + function countInNamespace(string memory namespace) external view returns (uint256 itemCount) { + return namespaceKeys_[namespace].length; + } + + /** + * @dev Get total number of namespaces + * @return totalNamespaces Total number of namespaces + */ + function namespaceCount() external view returns (uint256 totalNamespaces) { + return namespaces_.length; + } + + /** + * @dev Get total number of items across all namespaces + * @return totalItems Total number of items across all namespaces + */ + function totalCount() external view returns (uint256 totalItems) { + for (uint256 i = 0; i < namespaces_.length; i++) { + totalItems += namespaceKeys_[namespaces_[i]].length; + } + return totalItems; + } + + /** + * @dev Clear all data in a specific namespace + * @param namespace The namespace to clear + */ + function clearNamespace(string memory namespace) external { + require(namespaceExists_[namespace], "Namespace does not exist"); + + bytes[] storage keys = namespaceKeys_[namespace]; + + // Clear all data in the namespace + for (uint256 i = 0; i < keys.length; i++) { + bytes memory key = keys[i]; + delete namespaceStorage_[namespace][key]; + keyExists_[namespace][key] = false; + } + + // Clear keys array for the namespace + delete namespaceKeys_[namespace]; + + emit NamespaceCleared(namespace); + } + + /** + * @dev Clear all stored data across all namespaces (emergency function) + * Note: This function should be carefully protected in production + */ + function clearAll() external { + // Clear all namespaces + for (uint256 i = 0; i < namespaces_.length; i++) { + string memory namespace = namespaces_[i]; + bytes[] storage keys = namespaceKeys_[namespace]; + + // Clear all data in this namespace + for (uint256 j = 0; j < keys.length; j++) { + bytes memory key = keys[j]; + delete namespaceStorage_[namespace][key]; + keyExists_[namespace][key] = false; + } + + // Clear keys array for this namespace + delete namespaceKeys_[namespace]; + namespaceExists_[namespace] = false; + } + + // Clear namespaces array + delete namespaces_; + + emit AllDataCleared(); + } +} \ No newline at end of file diff --git a/systemcontracts/generic_storage.go b/systemcontracts/generic_storage.go new file mode 100644 index 0000000000..66163ed0c5 --- /dev/null +++ b/systemcontracts/generic_storage.go @@ -0,0 +1,439 @@ +package systemcontracts + +import ( + "math" + "math/big" + "strings" + + "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/common" + "github.com/pkg/errors" + "go.uber.org/zap" + + "github.com/iotexproject/iotex-core/v2/pkg/log" +) + +// GenericValue represents the value structure in the GenericStorage contract +type GenericValue struct { + PrimaryData []byte `json:"primaryData"` + SecondaryData []byte `json:"secondaryData"` + AuxiliaryData []byte `json:"auxiliaryData"` +} + +// BatchGetResult represents the result of a batch get operation +type BatchGetResult struct { + Values []GenericValue `json:"values"` + ExistsFlags []bool `json:"existsFlags"` +} + +// ListResult represents the result of a list operation +type ListResult struct { + KeyList [][]byte `json:"keyList"` + Values []GenericValue `json:"values"` + Total *big.Int `json:"total"` +} + +// ListKeysResult represents the result of a listKeys operation +type ListKeysResult struct { + KeyList [][]byte `json:"keyList"` + Total *big.Int `json:"total"` +} + +// GetResult represents the result of a get operation +type GetResult struct { + Value GenericValue `json:"value"` + KeyExists bool `json:"keyExists"` +} + +// GenericStorageContract provides an interface to interact with the GenericStorage smart contract +type GenericStorageContract struct { + contractAddress common.Address + backend ContractBackend + abi abi.ABI +} + +// NewGenericStorageContract creates a new GenericStorage contract instance +func NewGenericStorageContract(contractAddress common.Address, backend ContractBackend) (*GenericStorageContract, error) { + abi, err := abi.JSON(strings.NewReader(GenericStorageABI)) + if err != nil { + return nil, errors.Wrap(err, "failed to parse GenericStorage ABI") + } + + return &GenericStorageContract{ + contractAddress: contractAddress, + backend: backend, + abi: abi, + }, nil +} + +func (g *GenericStorageContract) Address() common.Address { + return g.contractAddress +} + +// Put stores data with the given key +func (g *GenericStorageContract) Put(key []byte, value GenericValue) error { + // Validate input + if len(key) == 0 { + return errors.New("key cannot be empty") + } + + // Pack the function call + data, err := g.abi.Pack("put", key, value) + if err != nil { + return errors.Wrap(err, "failed to pack put call") + } + + // Execute the transaction + callMsg := ðereum.CallMsg{ + To: &g.contractAddress, + Data: data, + Value: big.NewInt(0), + Gas: math.MaxUint64, + } + + if err := g.backend.Handle(callMsg); err != nil { + return errors.Wrap(err, "failed to execute put") + } + + log.L().Debug("Successfully stored data", + zap.String("key", string(key)), + zap.Int("primaryDataSize", len(value.PrimaryData)), + zap.Int("secondaryDataSize", len(value.SecondaryData)), + zap.Int("auxiliaryDataSize", len(value.AuxiliaryData))) + + return nil +} + +// PutSimple stores data with only primary data (convenience method) +func (g *GenericStorageContract) PutSimple(key []byte, data []byte) error { + value := GenericValue{ + PrimaryData: data, + SecondaryData: []byte{}, + AuxiliaryData: []byte{}, + } + return g.Put(key, value) +} + +// Get retrieves data by key +func (g *GenericStorageContract) Get(key []byte) (*GetResult, error) { + // Validate input + if len(key) == 0 { + return nil, errors.New("key cannot be empty") + } + + // Pack the function call + data, err := g.abi.Pack("get", key) + if err != nil { + return nil, errors.Wrap(err, "failed to pack get call") + } + + // Execute the call + callMsg := ðereum.CallMsg{ + To: &g.contractAddress, + Data: data, + Value: big.NewInt(0), + Gas: math.MaxUint64, + } + + result, err := g.backend.Call(callMsg) + if err != nil { + return nil, errors.Wrap(err, "failed to call get") + } + + // Unpack the result + var getResult struct { + Value GenericValue + KeyExists bool + } + + err = g.abi.UnpackIntoInterface(&getResult, "get", result) + if err != nil { + return nil, errors.Wrap(err, "failed to unpack get result") + } + + log.L().Debug("Successfully retrieved data", + zap.String("key", string(key)), + zap.Bool("exists", getResult.KeyExists)) + + return &GetResult{ + Value: getResult.Value, + KeyExists: getResult.KeyExists, + }, nil +} + +// Remove deletes data by key +func (g *GenericStorageContract) Remove(key []byte) error { + // Validate input + if len(key) == 0 { + return errors.New("key cannot be empty") + } + + // Pack the function call + data, err := g.abi.Pack("remove", key) + if err != nil { + return errors.Wrap(err, "failed to pack remove call") + } + + // Execute the transaction + callMsg := ðereum.CallMsg{ + To: &g.contractAddress, + Data: data, + Value: big.NewInt(0), + Gas: math.MaxUint64, + } + + if err := g.backend.Handle(callMsg); err != nil { + return errors.Wrap(err, "failed to execute remove") + } + + log.L().Debug("Successfully removed data", + zap.String("key", string(key))) + + return nil +} + +// BatchGet retrieves multiple values by their keys +func (g *GenericStorageContract) BatchGet(keys [][]byte) (*BatchGetResult, error) { + // Validate input + if len(keys) == 0 { + return &BatchGetResult{ + Values: []GenericValue{}, + ExistsFlags: []bool{}, + }, nil + } + + // Pack the function call + data, err := g.abi.Pack("batchGet", keys) + if err != nil { + return nil, errors.Wrap(err, "failed to pack batchGet call") + } + + // Execute the call + callMsg := ðereum.CallMsg{ + To: &g.contractAddress, + Data: data, + Value: big.NewInt(0), + Gas: math.MaxUint64, + } + + result, err := g.backend.Call(callMsg) + if err != nil { + return nil, errors.Wrap(err, "failed to call batchGet") + } + + // Unpack the result + var batchGetResult struct { + Values []GenericValue + ExistsFlags []bool + } + + err = g.abi.UnpackIntoInterface(&batchGetResult, "batchGet", result) + if err != nil { + return nil, errors.Wrap(err, "failed to unpack batchGet result") + } + + log.L().Debug("Successfully batch retrieved data", + zap.Int("requestedKeys", len(keys)), + zap.Int("returnedValues", len(batchGetResult.Values))) + + return &BatchGetResult{ + Values: batchGetResult.Values, + ExistsFlags: batchGetResult.ExistsFlags, + }, nil +} + +// List retrieves all stored data with pagination +func (g *GenericStorageContract) List(offset, limit uint64) (*ListResult, error) { + // Pack the function call + data, err := g.abi.Pack("list", new(big.Int).SetUint64(offset), new(big.Int).SetUint64(limit)) + if err != nil { + return nil, errors.Wrap(err, "failed to pack list call") + } + + // Execute the call + callMsg := ðereum.CallMsg{ + To: &g.contractAddress, + Data: data, + Value: big.NewInt(0), + Gas: math.MaxUint64, + } + + result, err := g.backend.Call(callMsg) + if err != nil { + return nil, errors.Wrap(err, "failed to call list") + } + + // Unpack the result + var listResult struct { + KeyList [][]byte + Values []GenericValue + Total *big.Int + } + + err = g.abi.UnpackIntoInterface(&listResult, "list", result) + if err != nil { + return nil, errors.Wrap(err, "failed to unpack list result") + } + + log.L().Debug("Successfully listed data", + zap.Uint64("offset", offset), + zap.Uint64("limit", limit), + zap.Int("returned", len(listResult.Values)), + zap.String("total", listResult.Total.String())) + + return &ListResult{ + KeyList: listResult.KeyList, + Values: listResult.Values, + Total: listResult.Total, + }, nil +} + +// ListKeys retrieves all keys with pagination (lightweight version) +func (g *GenericStorageContract) ListKeys(offset, limit uint64) (*ListKeysResult, error) { + // Pack the function call + data, err := g.abi.Pack("listKeys", new(big.Int).SetUint64(offset), new(big.Int).SetUint64(limit)) + if err != nil { + return nil, errors.Wrap(err, "failed to pack listKeys call") + } + + // Execute the call + callMsg := ðereum.CallMsg{ + To: &g.contractAddress, + Data: data, + Value: big.NewInt(0), + Gas: math.MaxUint64, + } + + result, err := g.backend.Call(callMsg) + if err != nil { + return nil, errors.Wrap(err, "failed to call listKeys") + } + + // Unpack the result + var listKeysResult struct { + KeyList [][]byte + Total *big.Int + } + + err = g.abi.UnpackIntoInterface(&listKeysResult, "listKeys", result) + if err != nil { + return nil, errors.Wrap(err, "failed to unpack listKeys result") + } + + log.L().Debug("Successfully listed keys", + zap.Uint64("offset", offset), + zap.Uint64("limit", limit), + zap.Int("returned", len(listKeysResult.KeyList)), + zap.String("total", listKeysResult.Total.String())) + + return &ListKeysResult{ + KeyList: listKeysResult.KeyList, + Total: listKeysResult.Total, + }, nil +} + +// Exists checks if a key exists in the storage +func (g *GenericStorageContract) Exists(key []byte) (bool, error) { + // Validate input + if len(key) == 0 { + return false, errors.New("key cannot be empty") + } + + // Pack the function call + data, err := g.abi.Pack("exists", key) + if err != nil { + return false, errors.Wrap(err, "failed to pack exists call") + } + + // Execute the call + callMsg := ðereum.CallMsg{ + To: &g.contractAddress, + Data: data, + Value: big.NewInt(0), + Gas: math.MaxUint64, + } + + result, err := g.backend.Call(callMsg) + if err != nil { + return false, errors.Wrap(err, "failed to call exists") + } + + // Unpack the result + var existsResult struct { + KeyExists bool + } + + err = g.abi.UnpackIntoInterface(&existsResult, "exists", result) + if err != nil { + return false, errors.Wrap(err, "failed to unpack exists result") + } + + log.L().Debug("Successfully checked key existence", + zap.String("key", string(key)), + zap.Bool("exists", existsResult.KeyExists)) + + return existsResult.KeyExists, nil +} + +// Count returns the total number of stored items +func (g *GenericStorageContract) Count() (*big.Int, error) { + // Pack the function call + data, err := g.abi.Pack("count") + if err != nil { + return nil, errors.Wrap(err, "failed to pack count call") + } + + // Execute the call + callMsg := ðereum.CallMsg{ + To: &g.contractAddress, + Data: data, + Value: big.NewInt(0), + Gas: math.MaxUint64, + } + + result, err := g.backend.Call(callMsg) + if err != nil { + return nil, errors.Wrap(err, "failed to call count") + } + + // Unpack the result + var countResult struct { + TotalCount *big.Int + } + + err = g.abi.UnpackIntoInterface(&countResult, "count", result) + if err != nil { + return nil, errors.Wrap(err, "failed to unpack count result") + } + + log.L().Debug("Successfully retrieved count", + zap.String("count", countResult.TotalCount.String())) + + return countResult.TotalCount, nil +} + +// Clear removes all stored data (emergency function) +func (g *GenericStorageContract) Clear() error { + // Pack the function call + data, err := g.abi.Pack("clear") + if err != nil { + return errors.Wrap(err, "failed to pack clear call") + } + + // Execute the transaction + callMsg := ðereum.CallMsg{ + To: &g.contractAddress, + Data: data, + Value: big.NewInt(0), + Gas: math.MaxUint64, + } + + if err := g.backend.Handle(callMsg); err != nil { + return errors.Wrap(err, "failed to execute clear") + } + + log.L().Debug("Successfully cleared all data") + + return nil +} diff --git a/systemcontracts/generic_storage_abi.go b/systemcontracts/generic_storage_abi.go new file mode 100644 index 0000000000..62d8977d3e --- /dev/null +++ b/systemcontracts/generic_storage_abi.go @@ -0,0 +1,301 @@ +package systemcontracts + +// GenericStorageABI is the ABI definition for the GenericStorage contract +const GenericStorageABI = `[ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes", + "name": "key", + "type": "bytes" + } + ], + "name": "DataDeleted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes", + "name": "key", + "type": "bytes" + } + ], + "name": "DataStored", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "keyCount", + "type": "uint256" + } + ], + "name": "BatchDataRetrieved", + "type": "event" + }, + { + "anonymous": false, + "inputs": [], + "name": "StorageCleared", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "bytes[]", + "name": "keyList", + "type": "bytes[]" + } + ], + "name": "batchGet", + "outputs": [ + { + "components": [ + { + "internalType": "bytes", + "name": "primaryData", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "secondaryData", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "auxiliaryData", + "type": "bytes" + } + ], + "internalType": "struct GenericStorage.GenericValue[]", + "name": "values", + "type": "tuple[]" + }, + { + "internalType": "bool[]", + "name": "existsFlags", + "type": "bool[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "clear", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "count", + "outputs": [ + { + "internalType": "uint256", + "name": "totalCount", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "key", + "type": "bytes" + } + ], + "name": "exists", + "outputs": [ + { + "internalType": "bool", + "name": "keyExists", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "key", + "type": "bytes" + } + ], + "name": "get", + "outputs": [ + { + "components": [ + { + "internalType": "bytes", + "name": "primaryData", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "secondaryData", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "auxiliaryData", + "type": "bytes" + } + ], + "internalType": "struct GenericStorage.GenericValue", + "name": "value", + "type": "tuple" + }, + { + "internalType": "bool", + "name": "keyExists", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "offset", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "limit", + "type": "uint256" + } + ], + "name": "list", + "outputs": [ + { + "internalType": "bytes[]", + "name": "keyList", + "type": "bytes[]" + }, + { + "components": [ + { + "internalType": "bytes", + "name": "primaryData", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "secondaryData", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "auxiliaryData", + "type": "bytes" + } + ], + "internalType": "struct GenericStorage.GenericValue[]", + "name": "values", + "type": "tuple[]" + }, + { + "internalType": "uint256", + "name": "total", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "offset", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "limit", + "type": "uint256" + } + ], + "name": "listKeys", + "outputs": [ + { + "internalType": "bytes[]", + "name": "keyList", + "type": "bytes[]" + }, + { + "internalType": "uint256", + "name": "total", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "key", + "type": "bytes" + }, + { + "components": [ + { + "internalType": "bytes", + "name": "primaryData", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "secondaryData", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "auxiliaryData", + "type": "bytes" + } + ], + "internalType": "struct GenericStorage.GenericValue", + "name": "value", + "type": "tuple" + } + ], + "name": "put", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "key", + "type": "bytes" + } + ], + "name": "remove", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +]` + +const GenericStorageByteCodeStr = "608060405234801561001057600080fd5b50612437806100206000396000f3fe608060405234801561001057600080fd5b50600436106100935760003560e01c806352efea6e1161006657806352efea6e1461013557806358edef4c1461013f57806379fc09a21461015b578063821bef2f1461018b578063d6d7d525146101bc57610093565b806306661abd14610098578063072957b0146100b657806342e1ae2e146100d257806350fd736714610103575b600080fd5b6100a06101ed565b6040516100ad9190611423565b60405180910390f35b6100d060048036038101906100cb919061165a565b6101fa565b005b6100ec60048036038101906100e791906117b8565b610385565b6040516100fa929190611a6a565b60405180910390f35b61011d60048036038101906101189190611acd565b6106ed565b60405161012c93929190611bcf565b60405180910390f35b61013d610b6d565b005b61015960048036038101906101549190611c14565b610cfb565b005b61017560048036038101906101709190611c14565b610f1e565b6040516101829190611c6c565b60405180910390f35b6101a560048036038101906101a09190611acd565b610f53565b6040516101b3929190611c87565b60405180910390f35b6101d660048036038101906101d19190611c14565b611122565b6040516101e4929190611d15565b60405180910390f35b6000600180549050905090565b600082511161023e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161023590611da2565b60405180910390fd5b60028260405161024e9190611dfe565b908152602001604051809103902060009054906101000a900460ff166102db576001829080600181540180825580915050600190039060005260206000200160009091909190915090816102a29190612021565b5060016002836040516102b59190611dfe565b908152602001604051809103902060006101000a81548160ff0219169083151502179055505b806000836040516102ec9190611dfe565b9081526020016040518091039020600082015181600001908161030f9190612021565b5060208201518160010190816103259190612021565b50604082015181600201908161033b9190612021565b509050508160405161034d9190611dfe565b60405180910390207f281be1a469724e78f8c4152bcc9fb70a95646c3e1e2ade9293d8d497c976338a60405160405180910390a25050565b606080825167ffffffffffffffff8111156103a3576103a261146d565b5b6040519080825280602002602001820160405280156103dc57816020015b6103c9611347565b8152602001906001900390816103c15790505b509150825167ffffffffffffffff8111156103fa576103f961146d565b5b6040519080825280602002602001820160405280156104285781602001602082028036833780820191505090505b50905060005b83518110156106e757600284828151811061044c5761044b6120f3565b5b60200260200101516040516104619190611dfe565b908152602001604051809103902060009054906101000a900460ff168282815181106104905761048f6120f3565b5b6020026020010190151590811515815250508181815181106104b5576104b46120f3565b5b6020026020010151156106da5760008482815181106104d7576104d66120f3565b5b60200260200101516040516104ec9190611dfe565b908152602001604051809103902060405180606001604052908160008201805461051590611e44565b80601f016020809104026020016040519081016040528092919081815260200182805461054190611e44565b801561058e5780601f106105635761010080835404028352916020019161058e565b820191906000526020600020905b81548152906001019060200180831161057157829003601f168201915b505050505081526020016001820180546105a790611e44565b80601f01602080910402602001604051908101604052809291908181526020018280546105d390611e44565b80156106205780601f106105f557610100808354040283529160200191610620565b820191906000526020600020905b81548152906001019060200180831161060357829003601f168201915b5050505050815260200160028201805461063990611e44565b80601f016020809104026020016040519081016040528092919081815260200182805461066590611e44565b80156106b25780601f10610687576101008083540402835291602001916106b2565b820191906000526020600020905b81548152906001019060200180831161069557829003601f168201915b5050505050815250508382815181106106ce576106cd6120f3565b5b60200260200101819052505b808060010191505061042e565b50915091565b606080600060018054905090508085106107ae57600067ffffffffffffffff81111561071c5761071b61146d565b5b60405190808252806020026020018201604052801561074f57816020015b606081526020019060019003908161073a5790505b509250600067ffffffffffffffff81111561076d5761076c61146d565b5b6040519080825280602002602001820160405280156107a657816020015b610793611347565b81526020019060019003908161078b5790505b509150610b66565b600085826107bc9190612151565b905060008186116107cd57856107cf565b815b90508067ffffffffffffffff8111156107eb576107ea61146d565b5b60405190808252806020026020018201604052801561081e57816020015b60608152602001906001900390816108095790505b5094508067ffffffffffffffff81111561083b5761083a61146d565b5b60405190808252806020026020018201604052801561087457816020015b610861611347565b8152602001906001900390816108595790505b50935060005b81811015610b625760006001828a6108929190612185565b815481106108a3576108a26120f3565b5b9060005260206000200180546108b890611e44565b80601f01602080910402602001604051908101604052809291908181526020018280546108e490611e44565b80156109315780601f1061090657610100808354040283529160200191610931565b820191906000526020600020905b81548152906001019060200180831161091457829003601f168201915b505050505090508087838151811061094c5761094b6120f3565b5b60200260200101819052506000816040516109679190611dfe565b908152602001604051809103902060405180606001604052908160008201805461099090611e44565b80601f01602080910402602001604051908101604052809291908181526020018280546109bc90611e44565b8015610a095780601f106109de57610100808354040283529160200191610a09565b820191906000526020600020905b8154815290600101906020018083116109ec57829003601f168201915b50505050508152602001600182018054610a2290611e44565b80601f0160208091040260200160405190810160405280929190818152602001828054610a4e90611e44565b8015610a9b5780601f10610a7057610100808354040283529160200191610a9b565b820191906000526020600020905b815481529060010190602001808311610a7e57829003601f168201915b50505050508152602001600282018054610ab490611e44565b80601f0160208091040260200160405190810160405280929190818152602001828054610ae090611e44565b8015610b2d5780601f10610b0257610100808354040283529160200191610b2d565b820191906000526020600020905b815481529060010190602001808311610b1057829003601f168201915b505050505081525050868381518110610b4957610b486120f3565b5b602002602001018190525050808060010191505061087a565b5050505b9250925092565b60005b600180549050811015610cbe57600060018281548110610b9357610b926120f3565b5b906000526020600020018054610ba890611e44565b80601f0160208091040260200160405190810160405280929190818152602001828054610bd490611e44565b8015610c215780601f10610bf657610100808354040283529160200191610c21565b820191906000526020600020905b815481529060010190602001808311610c0457829003601f168201915b50505050509050600081604051610c389190611dfe565b908152602001604051809103902060008082016000610c579190611368565b600182016000610c679190611368565b600282016000610c779190611368565b50506000600282604051610c8b9190611dfe565b908152602001604051809103902060006101000a81548160ff021916908315150217905550508080600101915050610b70565b5060016000610ccd91906113a8565b7f6c7e419df39ff46e811e7d979ebfd916b8d4960de06f479dc69cf8417cdb89e760405160405180910390a1565b600281604051610d0b9190611dfe565b908152602001604051809103902060009054906101000a900460ff16610d66576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610d5d90612205565b60405180910390fd5b600081604051610d769190611dfe565b908152602001604051809103902060008082016000610d959190611368565b600182016000610da59190611368565b600282016000610db59190611368565b50506000600282604051610dc99190611dfe565b908152602001604051809103902060006101000a81548160ff02191690831515021790555060005b600180549050811015610ed857818051906020012060018281548110610e1a57610e196120f3565b5b90600052602060002001604051610e3191906122a8565b604051809103902003610ecb576001808080549050610e509190612151565b81548110610e6157610e606120f3565b5b9060005260206000200160018281548110610e7f57610e7e6120f3565b5b906000526020600020019081610e9591906122ea565b506001805480610ea857610ea76123d2565b5b600190038181906000526020600020016000610ec49190611368565b9055610ed8565b8080600101915050610df1565b5080604051610ee79190611dfe565b60405180910390207f9248955bf73fd007be0a0d9dc13c36f9e61c3642fbac04d8ac592e0c21d0103760405160405180910390a250565b6000600282604051610f309190611dfe565b908152602001604051809103902060009054906101000a900460ff169050919050565b606060006001805490509050808410610fbc57600067ffffffffffffffff811115610f8157610f8061146d565b5b604051908082528060200260200182016040528015610fb457816020015b6060815260200190600190039081610f9f5790505b50915061111b565b60008482610fca9190612151565b90506000818511610fdb5784610fdd565b815b90508067ffffffffffffffff811115610ff957610ff861146d565b5b60405190808252806020026020018201604052801561102c57816020015b60608152602001906001900390816110175790505b50935060005b8181101561111757600181886110489190612185565b81548110611059576110586120f3565b5b90600052602060002001805461106e90611e44565b80601f016020809104026020016040519081016040528092919081815260200182805461109a90611e44565b80156110e75780601f106110bc576101008083540402835291602001916110e7565b820191906000526020600020905b8154815290600101906020018083116110ca57829003601f168201915b50505050508582815181106110ff576110fe6120f3565b5b60200260200101819052508080600101915050611032565b5050505b9250929050565b61112a611347565b600060028360405161113c9190611dfe565b908152602001604051809103902060009054906101000a900460ff1690508015611342576000836040516111709190611dfe565b908152602001604051809103902060405180606001604052908160008201805461119990611e44565b80601f01602080910402602001604051908101604052809291908181526020018280546111c590611e44565b80156112125780601f106111e757610100808354040283529160200191611212565b820191906000526020600020905b8154815290600101906020018083116111f557829003601f168201915b5050505050815260200160018201805461122b90611e44565b80601f016020809104026020016040519081016040528092919081815260200182805461125790611e44565b80156112a45780601f10611279576101008083540402835291602001916112a4565b820191906000526020600020905b81548152906001019060200180831161128757829003601f168201915b505050505081526020016002820180546112bd90611e44565b80601f01602080910402602001604051908101604052809291908181526020018280546112e990611e44565b80156113365780601f1061130b57610100808354040283529160200191611336565b820191906000526020600020905b81548152906001019060200180831161131957829003601f168201915b50505050508152505091505b915091565b60405180606001604052806060815260200160608152602001606081525090565b50805461137490611e44565b6000825580601f1061138657506113a5565b601f0160209004906000526020600020908101906113a491906113c9565b5b50565b50805460008255906000526020600020908101906113c691906113e6565b50565b5b808211156113e25760008160009055506001016113ca565b5090565b5b8082111561140657600081816113fd9190611368565b506001016113e7565b5090565b6000819050919050565b61141d8161140a565b82525050565b60006020820190506114386000830184611414565b92915050565b6000604051905090565b600080fd5b600080fd5b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6114a58261145c565b810181811067ffffffffffffffff821117156114c4576114c361146d565b5b80604052505050565b60006114d761143e565b90506114e3828261149c565b919050565b600067ffffffffffffffff8211156115035761150261146d565b5b61150c8261145c565b9050602081019050919050565b82818337600083830152505050565b600061153b611536846114e8565b6114cd565b90508281526020810184848401111561155757611556611457565b5b611562848285611519565b509392505050565b600082601f83011261157f5761157e611452565b5b813561158f848260208601611528565b91505092915050565b600080fd5b600080fd5b6000606082840312156115b8576115b7611598565b5b6115c260606114cd565b9050600082013567ffffffffffffffff8111156115e2576115e161159d565b5b6115ee8482850161156a565b600083015250602082013567ffffffffffffffff8111156116125761161161159d565b5b61161e8482850161156a565b602083015250604082013567ffffffffffffffff8111156116425761164161159d565b5b61164e8482850161156a565b60408301525092915050565b6000806040838503121561167157611670611448565b5b600083013567ffffffffffffffff81111561168f5761168e61144d565b5b61169b8582860161156a565b925050602083013567ffffffffffffffff8111156116bc576116bb61144d565b5b6116c8858286016115a2565b9150509250929050565b600067ffffffffffffffff8211156116ed576116ec61146d565b5b602082029050602081019050919050565b600080fd5b6000611716611711846116d2565b6114cd565b90508083825260208201905060208402830185811115611739576117386116fe565b5b835b8181101561178057803567ffffffffffffffff81111561175e5761175d611452565b5b80860161176b898261156a565b8552602085019450505060208101905061173b565b5050509392505050565b600082601f83011261179f5761179e611452565b5b81356117af848260208601611703565b91505092915050565b6000602082840312156117ce576117cd611448565b5b600082013567ffffffffffffffff8111156117ec576117eb61144d565b5b6117f88482850161178a565b91505092915050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b600081519050919050565b600082825260208201905092915050565b60005b8381101561186757808201518184015260208101905061184c565b60008484015250505050565b600061187e8261182d565b6118888185611838565b9350611898818560208601611849565b6118a18161145c565b840191505092915050565b600060608301600083015184820360008601526118c98282611873565b915050602083015184820360208601526118e38282611873565b915050604083015184820360408601526118fd8282611873565b9150508091505092915050565b600061191683836118ac565b905092915050565b6000602082019050919050565b600061193682611801565b611940818561180c565b9350836020820285016119528561181d565b8060005b8581101561198e578484038952815161196f858261190a565b945061197a8361191e565b925060208a01995050600181019050611956565b50829750879550505050505092915050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b60008115159050919050565b6119e1816119cc565b82525050565b60006119f383836119d8565b60208301905092915050565b6000602082019050919050565b6000611a17826119a0565b611a2181856119ab565b9350611a2c836119bc565b8060005b83811015611a5d578151611a4488826119e7565b9750611a4f836119ff565b925050600181019050611a30565b5085935050505092915050565b60006040820190508181036000830152611a84818561192b565b90508181036020830152611a988184611a0c565b90509392505050565b611aaa8161140a565b8114611ab557600080fd5b50565b600081359050611ac781611aa1565b92915050565b60008060408385031215611ae457611ae3611448565b5b6000611af285828601611ab8565b9250506020611b0385828601611ab8565b9150509250929050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b6000611b458383611873565b905092915050565b6000602082019050919050565b6000611b6582611b0d565b611b6f8185611b18565b935083602082028501611b8185611b29565b8060005b85811015611bbd5784840389528151611b9e8582611b39565b9450611ba983611b4d565b925060208a01995050600181019050611b85565b50829750879550505050505092915050565b60006060820190508181036000830152611be98186611b5a565b90508181036020830152611bfd818561192b565b9050611c0c6040830184611414565b949350505050565b600060208284031215611c2a57611c29611448565b5b600082013567ffffffffffffffff811115611c4857611c4761144d565b5b611c548482850161156a565b91505092915050565b611c66816119cc565b82525050565b6000602082019050611c816000830184611c5d565b92915050565b60006040820190508181036000830152611ca18185611b5a565b9050611cb06020830184611414565b9392505050565b60006060830160008301518482036000860152611cd48282611873565b91505060208301518482036020860152611cee8282611873565b91505060408301518482036040860152611d088282611873565b9150508091505092915050565b60006040820190508181036000830152611d2f8185611cb7565b9050611d3e6020830184611c5d565b9392505050565b600082825260208201905092915050565b7f4b65792063616e6e6f7420626520656d70747900000000000000000000000000600082015250565b6000611d8c601383611d45565b9150611d9782611d56565b602082019050919050565b60006020820190508181036000830152611dbb81611d7f565b9050919050565b600081905092915050565b6000611dd88261182d565b611de28185611dc2565b9350611df2818560208601611849565b80840191505092915050565b6000611e0a8284611dcd565b915081905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b60006002820490506001821680611e5c57607f821691505b602082108103611e6f57611e6e611e15565b5b50919050565b60008190508160005260206000209050919050565b60006020601f8301049050919050565b600082821b905092915050565b600060088302611ed77fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82611e9a565b611ee18683611e9a565b95508019841693508086168417925050509392505050565b6000819050919050565b6000611f1e611f19611f148461140a565b611ef9565b61140a565b9050919050565b6000819050919050565b611f3883611f03565b611f4c611f4482611f25565b848454611ea7565b825550505050565b600090565b611f61611f54565b611f6c818484611f2f565b505050565b5b81811015611f9057611f85600082611f59565b600181019050611f72565b5050565b601f821115611fd557611fa681611e75565b611faf84611e8a565b81016020851015611fbe578190505b611fd2611fca85611e8a565b830182611f71565b50505b505050565b600082821c905092915050565b6000611ff860001984600802611fda565b1980831691505092915050565b60006120118383611fe7565b9150826002028217905092915050565b61202a8261182d565b67ffffffffffffffff8111156120435761204261146d565b5b61204d8254611e44565b612058828285611f94565b600060209050601f83116001811461208b5760008415612079578287015190505b6120838582612005565b8655506120eb565b601f19841661209986611e75565b60005b828110156120c15784890151825560018201915060208501945060208101905061209c565b868310156120de57848901516120da601f891682611fe7565b8355505b6001600288020188555050505b505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600061215c8261140a565b91506121678361140a565b925082820390508181111561217f5761217e612122565b5b92915050565b60006121908261140a565b915061219b8361140a565b92508282019050808211156121b3576121b2612122565b5b92915050565b7f4b657920646f6573206e6f742065786973740000000000000000000000000000600082015250565b60006121ef601283611d45565b91506121fa826121b9565b602082019050919050565b6000602082019050818103600083015261221e816121e2565b9050919050565b6000815461223281611e44565b61223c8186611dc2565b94506001821660008114612257576001811461226c5761229f565b60ff198316865281151582028601935061229f565b61227585611e75565b60005b8381101561229757815481890152600182019150602081019050612278565b838801955050505b50505092915050565b60006122b48284612225565b915081905092915050565b6000815490506122ce81611e44565b9050919050565b60008190508160005260206000209050919050565b8181036122f85750506123d0565b612301826122bf565b67ffffffffffffffff81111561231a5761231961146d565b5b6123248254611e44565b61232f828285611f94565b6000601f83116001811461235e576000841561234c578287015490505b6123568582612005565b8655506123c9565b601f19841661236c876122d5565b965061237786611e75565b60005b8281101561239f5784890154825560018201915060018501945060208101905061237a565b868310156123bc57848901546123b8601f891682611fe7565b8355505b6001600288020188555050505b5050505050505b565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fdfea26469706673582212204b40ecf4db330d4b4846e1801fcbe82f88d48e72aca826e80879a5f928ee75b164736f6c63430008180033" diff --git a/systemcontracts/namespace_storage.go b/systemcontracts/namespace_storage.go new file mode 100644 index 0000000000..89b68f4476 --- /dev/null +++ b/systemcontracts/namespace_storage.go @@ -0,0 +1,680 @@ +package systemcontracts + +import ( + "math" + "math/big" + "strings" + + "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/common" + "github.com/pkg/errors" + "go.uber.org/zap" + + "github.com/iotexproject/iotex-core/v2/pkg/log" +) + +// NamespaceGenericValue represents the value structure in the NamespaceStorage contract +// This is the same as GenericValue but renamed to avoid conflicts +type NamespaceGenericValue struct { + PrimaryData []byte `json:"primaryData"` + SecondaryData []byte `json:"secondaryData"` + AuxiliaryData []byte `json:"auxiliaryData"` +} + +// NamespaceBatchGetResult represents the result of a batch get operation +type NamespaceBatchGetResult struct { + Values []NamespaceGenericValue `json:"values"` + ExistsFlags []bool `json:"existsFlags"` +} + +// NamespaceListResult represents the result of a list operation +type NamespaceListResult struct { + KeyList [][]byte `json:"keyList"` + Values []NamespaceGenericValue `json:"values"` + Total *big.Int `json:"total"` +} + +// NamespaceListKeysResult represents the result of a listKeys operation +type NamespaceListKeysResult struct { + KeyList [][]byte `json:"keyList"` + Total *big.Int `json:"total"` +} + +// NamespaceListNamespacesResult represents the result of a listNamespaces operation +type NamespaceListNamespacesResult struct { + NamespaceList []string `json:"namespaceList"` + Counts []*big.Int `json:"counts"` + Total *big.Int `json:"total"` +} + +// NamespaceGetResult represents the result of a get operation +type NamespaceGetResult struct { + Value NamespaceGenericValue `json:"value"` + KeyExists bool `json:"keyExists"` +} + +// NamespaceStorageContract provides an interface to interact with the NamespaceStorage smart contract +type NamespaceStorageContract struct { + contractAddress common.Address + backend ContractBackend + abi abi.ABI +} + +// NewNamespaceStorageContract creates a new NamespaceStorage contract instance +func NewNamespaceStorageContract(contractAddress common.Address, backend ContractBackend) (*NamespaceStorageContract, error) { + abi, err := abi.JSON(strings.NewReader(NamespaceStorageABI)) + if err != nil { + return nil, errors.Wrap(err, "failed to parse NamespaceStorage ABI") + } + + return &NamespaceStorageContract{ + contractAddress: contractAddress, + backend: backend, + abi: abi, + }, nil +} + +// Address returns the contract address +func (ns *NamespaceStorageContract) Address() common.Address { + return ns.contractAddress +} + +// Put stores data with the given namespace and key +func (ns *NamespaceStorageContract) Put(namespace string, key []byte, value NamespaceGenericValue) error { + // Validate input + if len(namespace) == 0 { + return errors.New("namespace cannot be empty") + } + if len(key) == 0 { + return errors.New("key cannot be empty") + } + + // Pack the function call + data, err := ns.abi.Pack("put", namespace, key, value) + if err != nil { + return errors.Wrap(err, "failed to pack put call") + } + + // Execute the transaction + callMsg := ðereum.CallMsg{ + To: &ns.contractAddress, + Data: data, + Value: big.NewInt(0), + Gas: math.MaxUint64, + } + + if err := ns.backend.Handle(callMsg); err != nil { + return errors.Wrap(err, "failed to execute put") + } + + log.L().Debug("Successfully stored data", + zap.String("namespace", namespace), + zap.String("key", string(key))) + + return nil +} + +// Get retrieves data by namespace and key +func (ns *NamespaceStorageContract) Get(namespace string, key []byte) (*NamespaceGetResult, error) { + // Validate input + if len(namespace) == 0 { + return nil, errors.New("namespace cannot be empty") + } + if len(key) == 0 { + return nil, errors.New("key cannot be empty") + } + + // Pack the function call + data, err := ns.abi.Pack("get", namespace, key) + if err != nil { + return nil, errors.Wrap(err, "failed to pack get call") + } + + // Execute the call + callMsg := ðereum.CallMsg{ + To: &ns.contractAddress, + Data: data, + Value: big.NewInt(0), + Gas: math.MaxUint64, + } + + result, err := ns.backend.Call(callMsg) + if err != nil { + return nil, errors.Wrap(err, "failed to call get") + } + + // Unpack the result + var getResult struct { + Value NamespaceGenericValue + KeyExists bool + } + + err = ns.abi.UnpackIntoInterface(&getResult, "get", result) + if err != nil { + return nil, errors.Wrap(err, "failed to unpack get result") + } + + log.L().Debug("Successfully retrieved data", + zap.String("namespace", namespace), + zap.String("key", string(key)), + zap.Bool("exists", getResult.KeyExists)) + + return &NamespaceGetResult{ + Value: getResult.Value, + KeyExists: getResult.KeyExists, + }, nil +} + +// Remove deletes data by namespace and key +func (ns *NamespaceStorageContract) Remove(namespace string, key []byte) error { + // Validate input + if len(namespace) == 0 { + return errors.New("namespace cannot be empty") + } + if len(key) == 0 { + return errors.New("key cannot be empty") + } + + // Pack the function call + data, err := ns.abi.Pack("remove", namespace, key) + if err != nil { + return errors.Wrap(err, "failed to pack remove call") + } + + // Execute the transaction + callMsg := ðereum.CallMsg{ + To: &ns.contractAddress, + Data: data, + Value: big.NewInt(0), + Gas: math.MaxUint64, + } + + if err := ns.backend.Handle(callMsg); err != nil { + return errors.Wrap(err, "failed to execute remove") + } + + log.L().Debug("Successfully removed data", + zap.String("namespace", namespace), + zap.String("key", string(key))) + + return nil +} + +// Exists checks if a key exists in a namespace +func (ns *NamespaceStorageContract) Exists(namespace string, key []byte) (bool, error) { + // Validate input + if len(namespace) == 0 { + return false, errors.New("namespace cannot be empty") + } + if len(key) == 0 { + return false, errors.New("key cannot be empty") + } + + // Pack the function call + data, err := ns.abi.Pack("exists", namespace, key) + if err != nil { + return false, errors.Wrap(err, "failed to pack exists call") + } + + // Execute the call + callMsg := ðereum.CallMsg{ + To: &ns.contractAddress, + Data: data, + Value: big.NewInt(0), + Gas: math.MaxUint64, + } + + result, err := ns.backend.Call(callMsg) + if err != nil { + return false, errors.Wrap(err, "failed to call exists") + } + + // Unpack the result + var keyExists bool + err = ns.abi.UnpackIntoInterface(&keyExists, "exists", result) + if err != nil { + return false, errors.Wrap(err, "failed to unpack exists result") + } + + return keyExists, nil +} + +// BatchGet retrieves multiple values by their keys within a namespace +func (ns *NamespaceStorageContract) BatchGet(namespace string, keys [][]byte) (*NamespaceBatchGetResult, error) { + // Validate input + if len(namespace) == 0 { + return nil, errors.New("namespace cannot be empty") + } + if len(keys) == 0 { + return &NamespaceBatchGetResult{ + Values: []NamespaceGenericValue{}, + ExistsFlags: []bool{}, + }, nil + } + + // Pack the function call + data, err := ns.abi.Pack("batchGet", namespace, keys) + if err != nil { + return nil, errors.Wrap(err, "failed to pack batchGet call") + } + + // Execute the call + callMsg := ðereum.CallMsg{ + To: &ns.contractAddress, + Data: data, + Value: big.NewInt(0), + Gas: math.MaxUint64, + } + + result, err := ns.backend.Call(callMsg) + if err != nil { + return nil, errors.Wrap(err, "failed to call batchGet") + } + + // Unpack the result + var batchResult struct { + Values []NamespaceGenericValue + ExistsFlags []bool + } + + err = ns.abi.UnpackIntoInterface(&batchResult, "batchGet", result) + if err != nil { + return nil, errors.Wrap(err, "failed to unpack batchGet result") + } + + log.L().Debug("Successfully batch retrieved data", + zap.String("namespace", namespace), + zap.Int("count", len(keys))) + + return &NamespaceBatchGetResult{ + Values: batchResult.Values, + ExistsFlags: batchResult.ExistsFlags, + }, nil +} + +// BatchPut stores multiple key-value pairs in the same namespace +func (ns *NamespaceStorageContract) BatchPut(namespace string, keys [][]byte, values []NamespaceGenericValue) error { + // Validate input + if len(namespace) == 0 { + return errors.New("namespace cannot be empty") + } + if len(keys) != len(values) { + return errors.New("keys and values arrays must have same length") + } + if len(keys) == 0 { + return nil // Nothing to do + } + + // Pack the function call + data, err := ns.abi.Pack("batchPut", namespace, keys, values) + if err != nil { + return errors.Wrap(err, "failed to pack batchPut call") + } + + // Execute the transaction + callMsg := ðereum.CallMsg{ + To: &ns.contractAddress, + Data: data, + Value: big.NewInt(0), + Gas: math.MaxUint64, + } + + if err := ns.backend.Handle(callMsg); err != nil { + return errors.Wrap(err, "failed to execute batchPut") + } + + log.L().Debug("Successfully batch stored data", + zap.String("namespace", namespace), + zap.Int("count", len(keys))) + + return nil +} + +// List retrieves all stored data in a namespace with pagination +func (ns *NamespaceStorageContract) List(namespace string, offset, limit *big.Int) (*NamespaceListResult, error) { + // Validate input + if len(namespace) == 0 { + return nil, errors.New("namespace cannot be empty") + } + if offset == nil { + offset = big.NewInt(0) + } + if limit == nil { + limit = big.NewInt(100) // Default limit + } + + // Pack the function call + data, err := ns.abi.Pack("list", namespace, offset, limit) + if err != nil { + return nil, errors.Wrap(err, "failed to pack list call") + } + + // Execute the call + callMsg := ðereum.CallMsg{ + To: &ns.contractAddress, + Data: data, + Value: big.NewInt(0), + Gas: math.MaxUint64, + } + + result, err := ns.backend.Call(callMsg) + if err != nil { + return nil, errors.Wrap(err, "failed to call list") + } + + // Unpack the result + var listResult struct { + KeyList [][]byte + Values []NamespaceGenericValue + Total *big.Int + } + + err = ns.abi.UnpackIntoInterface(&listResult, "list", result) + if err != nil { + return nil, errors.Wrap(err, "failed to unpack list result") + } + + log.L().Debug("Successfully listed data", + zap.String("namespace", namespace), + zap.String("total", listResult.Total.String())) + + return &NamespaceListResult{ + KeyList: listResult.KeyList, + Values: listResult.Values, + Total: listResult.Total, + }, nil +} + +// ListKeys retrieves all keys in a namespace with pagination +func (ns *NamespaceStorageContract) ListKeys(namespace string, offset, limit *big.Int) (*NamespaceListKeysResult, error) { + // Validate input + if len(namespace) == 0 { + return nil, errors.New("namespace cannot be empty") + } + if offset == nil { + offset = big.NewInt(0) + } + if limit == nil { + limit = big.NewInt(100) // Default limit + } + + // Pack the function call + data, err := ns.abi.Pack("listKeys", namespace, offset, limit) + if err != nil { + return nil, errors.Wrap(err, "failed to pack listKeys call") + } + + // Execute the call + callMsg := ðereum.CallMsg{ + To: &ns.contractAddress, + Data: data, + Value: big.NewInt(0), + Gas: math.MaxUint64, + } + + result, err := ns.backend.Call(callMsg) + if err != nil { + return nil, errors.Wrap(err, "failed to call listKeys") + } + + // Unpack the result + var listKeysResult struct { + KeyList [][]byte + Total *big.Int + } + + err = ns.abi.UnpackIntoInterface(&listKeysResult, "listKeys", result) + if err != nil { + return nil, errors.Wrap(err, "failed to unpack listKeys result") + } + + log.L().Debug("Successfully listed keys", + zap.String("namespace", namespace), + zap.String("total", listKeysResult.Total.String())) + + return &NamespaceListKeysResult{ + KeyList: listKeysResult.KeyList, + Total: listKeysResult.Total, + }, nil +} + +// ListNamespaces retrieves all namespaces with pagination +func (ns *NamespaceStorageContract) ListNamespaces(offset, limit *big.Int) (*NamespaceListNamespacesResult, error) { + if offset == nil { + offset = big.NewInt(0) + } + if limit == nil { + limit = big.NewInt(100) // Default limit + } + + // Pack the function call + data, err := ns.abi.Pack("listNamespaces", offset, limit) + if err != nil { + return nil, errors.Wrap(err, "failed to pack listNamespaces call") + } + + // Execute the call + callMsg := ðereum.CallMsg{ + To: &ns.contractAddress, + Data: data, + Value: big.NewInt(0), + Gas: math.MaxUint64, + } + + result, err := ns.backend.Call(callMsg) + if err != nil { + return nil, errors.Wrap(err, "failed to call listNamespaces") + } + + // Unpack the result + var listNamespacesResult struct { + NamespaceList []string + Counts []*big.Int + Total *big.Int + } + + err = ns.abi.UnpackIntoInterface(&listNamespacesResult, "listNamespaces", result) + if err != nil { + return nil, errors.Wrap(err, "failed to unpack listNamespaces result") + } + + log.L().Debug("Successfully listed namespaces", + zap.String("total", listNamespacesResult.Total.String())) + + return &NamespaceListNamespacesResult{ + NamespaceList: listNamespacesResult.NamespaceList, + Counts: listNamespacesResult.Counts, + Total: listNamespacesResult.Total, + }, nil +} + +// HasNamespace checks if a namespace exists +func (ns *NamespaceStorageContract) HasNamespace(namespace string) (bool, error) { + // Validate input + if len(namespace) == 0 { + return false, errors.New("namespace cannot be empty") + } + + // Pack the function call + data, err := ns.abi.Pack("hasNamespace", namespace) + if err != nil { + return false, errors.Wrap(err, "failed to pack hasNamespace call") + } + + // Execute the call + callMsg := ðereum.CallMsg{ + To: &ns.contractAddress, + Data: data, + Value: big.NewInt(0), + Gas: math.MaxUint64, + } + + result, err := ns.backend.Call(callMsg) + if err != nil { + return false, errors.Wrap(err, "failed to call hasNamespace") + } + + // Unpack the result + var nsExists bool + err = ns.abi.UnpackIntoInterface(&nsExists, "hasNamespace", result) + if err != nil { + return false, errors.Wrap(err, "failed to unpack hasNamespace result") + } + + return nsExists, nil +} + +// CountInNamespace returns the number of items in a namespace +func (ns *NamespaceStorageContract) CountInNamespace(namespace string) (*big.Int, error) { + // Validate input + if len(namespace) == 0 { + return nil, errors.New("namespace cannot be empty") + } + + // Pack the function call + data, err := ns.abi.Pack("countInNamespace", namespace) + if err != nil { + return nil, errors.Wrap(err, "failed to pack countInNamespace call") + } + + // Execute the call + callMsg := ðereum.CallMsg{ + To: &ns.contractAddress, + Data: data, + Value: big.NewInt(0), + Gas: math.MaxUint64, + } + + result, err := ns.backend.Call(callMsg) + if err != nil { + return nil, errors.Wrap(err, "failed to call countInNamespace") + } + + // Unpack the result + var itemCount *big.Int + err = ns.abi.UnpackIntoInterface(&itemCount, "countInNamespace", result) + if err != nil { + return nil, errors.Wrap(err, "failed to unpack countInNamespace result") + } + + return itemCount, nil +} + +// NamespaceCount returns the total number of namespaces +func (ns *NamespaceStorageContract) NamespaceCount() (*big.Int, error) { + // Pack the function call + data, err := ns.abi.Pack("namespaceCount") + if err != nil { + return nil, errors.Wrap(err, "failed to pack namespaceCount call") + } + + // Execute the call + callMsg := ðereum.CallMsg{ + To: &ns.contractAddress, + Data: data, + Value: big.NewInt(0), + Gas: math.MaxUint64, + } + + result, err := ns.backend.Call(callMsg) + if err != nil { + return nil, errors.Wrap(err, "failed to call namespaceCount") + } + + // Unpack the result + var totalNamespaces *big.Int + err = ns.abi.UnpackIntoInterface(&totalNamespaces, "namespaceCount", result) + if err != nil { + return nil, errors.Wrap(err, "failed to unpack namespaceCount result") + } + + return totalNamespaces, nil +} + +// TotalCount returns the total number of items across all namespaces +func (ns *NamespaceStorageContract) TotalCount() (*big.Int, error) { + // Pack the function call + data, err := ns.abi.Pack("totalCount") + if err != nil { + return nil, errors.Wrap(err, "failed to pack totalCount call") + } + + // Execute the call + callMsg := ðereum.CallMsg{ + To: &ns.contractAddress, + Data: data, + Value: big.NewInt(0), + Gas: math.MaxUint64, + } + + result, err := ns.backend.Call(callMsg) + if err != nil { + return nil, errors.Wrap(err, "failed to call totalCount") + } + + // Unpack the result + var totalItems *big.Int + err = ns.abi.UnpackIntoInterface(&totalItems, "totalCount", result) + if err != nil { + return nil, errors.Wrap(err, "failed to unpack totalCount result") + } + + return totalItems, nil +} + +// ClearNamespace clears all data in a specific namespace +func (ns *NamespaceStorageContract) ClearNamespace(namespace string) error { + // Validate input + if len(namespace) == 0 { + return errors.New("namespace cannot be empty") + } + + // Pack the function call + data, err := ns.abi.Pack("clearNamespace", namespace) + if err != nil { + return errors.Wrap(err, "failed to pack clearNamespace call") + } + + // Execute the transaction + callMsg := ðereum.CallMsg{ + To: &ns.contractAddress, + Data: data, + Value: big.NewInt(0), + Gas: math.MaxUint64, + } + + if err := ns.backend.Handle(callMsg); err != nil { + return errors.Wrap(err, "failed to execute clearNamespace") + } + + log.L().Debug("Successfully cleared namespace", + zap.String("namespace", namespace)) + + return nil +} + +// ClearAll clears all stored data across all namespaces (emergency function) +func (ns *NamespaceStorageContract) ClearAll() error { + // Pack the function call + data, err := ns.abi.Pack("clearAll") + if err != nil { + return errors.Wrap(err, "failed to pack clearAll call") + } + + // Execute the transaction + callMsg := ðereum.CallMsg{ + To: &ns.contractAddress, + Data: data, + Value: big.NewInt(0), + Gas: math.MaxUint64, + } + + if err := ns.backend.Handle(callMsg); err != nil { + return errors.Wrap(err, "failed to execute clearAll") + } + + log.L().Debug("Successfully cleared all data") + + return nil +} diff --git a/systemcontracts/namespace_storage_abi.go b/systemcontracts/namespace_storage_abi.go new file mode 100644 index 0000000000..da1745c18e --- /dev/null +++ b/systemcontracts/namespace_storage_abi.go @@ -0,0 +1,506 @@ +package systemcontracts + +// NamespaceStorageABI is the ABI definition for the NamespaceStorage contract +const NamespaceStorageABI = `[ + { + "anonymous": false, + "inputs": [], + "name": "AllDataCleared", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "string", + "name": "namespace", + "type": "string" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "keyCount", + "type": "uint256" + } + ], + "name": "BatchDataRetrieved", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "string", + "name": "namespace", + "type": "string" + }, + { + "indexed": true, + "internalType": "bytes", + "name": "key", + "type": "bytes" + } + ], + "name": "DataDeleted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "string", + "name": "namespace", + "type": "string" + }, + { + "indexed": true, + "internalType": "bytes", + "name": "key", + "type": "bytes" + } + ], + "name": "DataStored", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "string", + "name": "namespace", + "type": "string" + } + ], + "name": "NamespaceCleared", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "namespace", + "type": "string" + }, + { + "internalType": "bytes[]", + "name": "keyList", + "type": "bytes[]" + } + ], + "name": "batchGet", + "outputs": [ + { + "components": [ + { + "internalType": "bytes", + "name": "primaryData", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "secondaryData", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "auxiliaryData", + "type": "bytes" + } + ], + "internalType": "struct NamespaceStorage.GenericValue[]", + "name": "values", + "type": "tuple[]" + }, + { + "internalType": "bool[]", + "name": "existsFlags", + "type": "bool[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "namespace", + "type": "string" + }, + { + "internalType": "bytes[]", + "name": "keys", + "type": "bytes[]" + }, + { + "components": [ + { + "internalType": "bytes", + "name": "primaryData", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "secondaryData", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "auxiliaryData", + "type": "bytes" + } + ], + "internalType": "struct NamespaceStorage.GenericValue[]", + "name": "values", + "type": "tuple[]" + } + ], + "name": "batchPut", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "clearAll", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "namespace", + "type": "string" + } + ], + "name": "clearNamespace", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "namespace", + "type": "string" + } + ], + "name": "countInNamespace", + "outputs": [ + { + "internalType": "uint256", + "name": "itemCount", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "namespace", + "type": "string" + }, + { + "internalType": "bytes", + "name": "key", + "type": "bytes" + } + ], + "name": "exists", + "outputs": [ + { + "internalType": "bool", + "name": "keyExists", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "namespace", + "type": "string" + }, + { + "internalType": "bytes", + "name": "key", + "type": "bytes" + } + ], + "name": "get", + "outputs": [ + { + "components": [ + { + "internalType": "bytes", + "name": "primaryData", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "secondaryData", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "auxiliaryData", + "type": "bytes" + } + ], + "internalType": "struct NamespaceStorage.GenericValue", + "name": "value", + "type": "tuple" + }, + { + "internalType": "bool", + "name": "keyExists", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "namespace", + "type": "string" + } + ], + "name": "hasNamespace", + "outputs": [ + { + "internalType": "bool", + "name": "nsExists", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "namespace", + "type": "string" + }, + { + "internalType": "uint256", + "name": "offset", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "limit", + "type": "uint256" + } + ], + "name": "list", + "outputs": [ + { + "internalType": "bytes[]", + "name": "keyList", + "type": "bytes[]" + }, + { + "components": [ + { + "internalType": "bytes", + "name": "primaryData", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "secondaryData", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "auxiliaryData", + "type": "bytes" + } + ], + "internalType": "struct NamespaceStorage.GenericValue[]", + "name": "values", + "type": "tuple[]" + }, + { + "internalType": "uint256", + "name": "total", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "namespace", + "type": "string" + }, + { + "internalType": "uint256", + "name": "offset", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "limit", + "type": "uint256" + } + ], + "name": "listKeys", + "outputs": [ + { + "internalType": "bytes[]", + "name": "keyList", + "type": "bytes[]" + }, + { + "internalType": "uint256", + "name": "total", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "offset", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "limit", + "type": "uint256" + } + ], + "name": "listNamespaces", + "outputs": [ + { + "internalType": "string[]", + "name": "namespaceList", + "type": "string[]" + }, + { + "internalType": "uint256[]", + "name": "counts", + "type": "uint256[]" + }, + { + "internalType": "uint256", + "name": "total", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "namespaceCount", + "outputs": [ + { + "internalType": "uint256", + "name": "totalNamespaces", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "namespace", + "type": "string" + }, + { + "internalType": "bytes", + "name": "key", + "type": "bytes" + }, + { + "components": [ + { + "internalType": "bytes", + "name": "primaryData", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "secondaryData", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "auxiliaryData", + "type": "bytes" + } + ], + "internalType": "struct NamespaceStorage.GenericValue", + "name": "value", + "type": "tuple" + } + ], + "name": "put", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "namespace", + "type": "string" + }, + { + "internalType": "bytes", + "name": "key", + "type": "bytes" + } + ], + "name": "remove", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "totalCount", + "outputs": [ + { + "internalType": "uint256", + "name": "totalItems", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + } +]` + +// NamespaceStorageContractByteCodeStr is the bytecode for the NamespaceStorage contract +const NamespaceStorageContractByteCodeStr = "608060405234801561001057600080fd5b50613df1806100206000396000f3fe608060405234801561001057600080fd5b50600436106100f55760003560e01c8063912f309511610097578063c9037d2d11610066578063c9037d2d146102b1578063d1e96865146102e1578063ebb689a114610311578063f53504231461031b576100f5565b8063912f309514610214578063a2bc7a1c14610246578063aff6274514610262578063b40ec02b14610293576100f5565b80634b6b9a8c116100d35780634b6b9a8c146101655780634e8bfabb1461019657806353df2b27146101b257806370eafd18146101e4576100f5565b806304e52369146100fa57806312862f7f1461011657806334eafb1114610147575b600080fd5b610114600480360381019061010f91906126b3565b610337565b005b610130600480360381019061012b9190612811565b61064f565b60405161013e929190612af2565b60405180910390f35b61014f6109f1565b60405161015c9190612b42565b60405180910390f35b61017f600480360381019061017a9190612b89565b610a63565b60405161018d929190612cba565b60405180910390f35b6101b060048036038101906101ab9190612e8d565b610c54565b005b6101cc60048036038101906101c79190612f34565b61105b565b6040516101db93929190613149565b60405180910390f35b6101fe60048036038101906101f9919061318e565b611309565b60405161020b91906131e6565b60405180910390f35b61022e60048036038101906102299190612b89565b61133e565b60405161023d93929190613201565b60405180910390f35b610260600480360381019061025b919061318e565b6117fd565b005b61027c600480360381019061027791906126b3565b611a82565b60405161028a9291906132a4565b60405180910390f35b61029b611ce1565b6040516102a89190612b42565b60405180910390f35b6102cb60048036038101906102c6919061318e565b611cee565b6040516102d89190612b42565b60405180910390f35b6102fb60048036038101906102f691906126b3565b611d19565b60405161030891906131e6565b60405180910390f35b610319611d6b565b005b610335600480360381019061033091906132d4565b61207d565b005b60048260405161034791906133b7565b908152602001604051809103902060009054906101000a900460ff166103a2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103999061342b565b60405180910390fd5b6002826040516103b291906133b7565b9081526020016040518091039020816040516103ce9190613487565b908152602001604051809103902060009054906101000a900460ff16610429576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610420906134ea565b60405180910390fd5b60008260405161043991906133b7565b9081526020016040518091039020816040516104559190613487565b9081526020016040518091039020600080820160006104749190612370565b6001820160006104849190612370565b6002820160006104949190612370565b505060006002836040516104a891906133b7565b9081526020016040518091039020826040516104c49190613487565b908152602001604051809103902060006101000a81548160ff02191690831515021790555060006001836040516104fb91906133b7565b9081526020016040518091039020905060005b81805490508110156105f15782805190602001208282815481106105355761053461350a565b5b9060005260206000200160405161054c9190613631565b6040518091039020036105e457816001838054905061056b9190613677565b8154811061057c5761057b61350a565b5b906000526020600020018282815481106105995761059861350a565b5b9060005260206000200190816105af919061386d565b50818054806105c1576105c0613955565b5b6001900381819060005260206000200160006105dd9190612370565b90556105f1565b808060010191505061050e565b50816040516106009190613487565b60405180910390208360405161061691906133b7565b60405180910390207faf8967c7b21227d5d987c31cd064433b027cf5bd93330cdbe6b62909093c417260405160405180910390a3505050565b606080825167ffffffffffffffff81111561066d5761066c6124e7565b5b6040519080825280602002602001820160405280156106a657816020015b6106936123b0565b81526020019060019003908161068b5790505b509150825167ffffffffffffffff8111156106c4576106c36124e7565b5b6040519080825280602002602001820160405280156106f25781602001602082028036833780820191505090505b50905060005b83518110156109e95760028560405161071191906133b7565b90815260200160405180910390208482815181106107325761073161350a565b5b60200260200101516040516107479190613487565b908152602001604051809103902060009054906101000a900460ff168282815181106107765761077561350a565b5b60200260200101901515908115158152505081818151811061079b5761079a61350a565b5b6020026020010151156109dc576000856040516107b891906133b7565b90815260200160405180910390208482815181106107d9576107d861350a565b5b60200260200101516040516107ee9190613487565b908152602001604051809103902060405180606001604052908160008201805461081790613568565b80601f016020809104026020016040519081016040528092919081815260200182805461084390613568565b80156108905780601f1061086557610100808354040283529160200191610890565b820191906000526020600020905b81548152906001019060200180831161087357829003601f168201915b505050505081526020016001820180546108a990613568565b80601f01602080910402602001604051908101604052809291908181526020018280546108d590613568565b80156109225780601f106108f757610100808354040283529160200191610922565b820191906000526020600020905b81548152906001019060200180831161090557829003601f168201915b5050505050815260200160028201805461093b90613568565b80601f016020809104026020016040519081016040528092919081815260200182805461096790613568565b80156109b45780601f10610989576101008083540402835291602001916109b4565b820191906000526020600020905b81548152906001019060200180831161099757829003601f168201915b5050505050815250508382815181106109d0576109cf61350a565b5b60200260200101819052505b80806001019150506106f8565b509250929050565b600080600090505b600380549050811015610a5f57600160038281548110610a1c57610a1b61350a565b5b90600052602060002001604051610a339190613a1c565b90815260200160405180910390208054905082610a509190613a33565b915080806001019150506109f9565b5090565b6060600080600186604051610a7891906133b7565b9081526020016040518091039020905080805490509150818510610aed57600067ffffffffffffffff811115610ab157610ab06124e7565b5b604051908082528060200260200182016040528015610ae457816020015b6060815260200190600190039081610acf5790505b50925050610c4c565b60008583610afb9190613677565b90506000818611610b0c5785610b0e565b815b90508067ffffffffffffffff811115610b2a57610b296124e7565b5b604051908082528060200260200182016040528015610b5d57816020015b6060815260200190600190039081610b485790505b50945060005b81811015610c4757838189610b789190613a33565b81548110610b8957610b8861350a565b5b906000526020600020018054610b9e90613568565b80601f0160208091040260200160405190810160405280929190818152602001828054610bca90613568565b8015610c175780601f10610bec57610100808354040283529160200191610c17565b820191906000526020600020905b815481529060010190602001808311610bfa57829003601f168201915b5050505050868281518110610c2f57610c2e61350a565b5b60200260200101819052508080600101915050610b63565b505050505b935093915050565b8051825114610c98576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610c8f90613ad9565b60405180910390fd5b6000835111610cdc576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610cd390613b45565b60405180910390fd5b600483604051610cec91906133b7565b908152602001604051809103902060009054906101000a900460ff16610d7957600383908060018154018082558091505060019003906000526020600020016000909190919091509081610d409190613bab565b506001600484604051610d5391906133b7565b908152602001604051809103902060006101000a81548160ff0219169083151502179055505b60005b8251811015611055576000838281518110610d9a57610d9961350a565b5b60200260200101515111610de3576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610dda90613cc9565b60405180910390fd5b600284604051610df391906133b7565b9081526020016040518091039020838281518110610e1457610e1361350a565b5b6020026020010151604051610e299190613487565b908152602001604051809103902060009054906101000a900460ff16610f2257600184604051610e5991906133b7565b9081526020016040518091039020838281518110610e7a57610e7961350a565b5b6020026020010151908060018154018082558091505060019003906000526020600020016000909190919091509081610eb39190613ce9565b506001600285604051610ec691906133b7565b9081526020016040518091039020848381518110610ee757610ee661350a565b5b6020026020010151604051610efc9190613487565b908152602001604051809103902060006101000a81548160ff0219169083151502179055505b818181518110610f3557610f3461350a565b5b6020026020010151600085604051610f4d91906133b7565b9081526020016040518091039020848381518110610f6e57610f6d61350a565b5b6020026020010151604051610f839190613487565b90815260200160405180910390206000820151816000019081610fa69190613ce9565b506020820151816001019081610fbc9190613ce9565b506040820151816002019081610fd29190613ce9565b50905050828181518110610fe957610fe861350a565b5b6020026020010151604051610ffe9190613487565b60405180910390208460405161101491906133b7565b60405180910390207fd00871f87cd1b1b4e50e5be511f060478c06a013856673c392f2adbfa65df8ad60405160405180910390a38080600101915050610d7c565b50505050565b6060806000600380549050905080851061111157600067ffffffffffffffff81111561108a576110896124e7565b5b6040519080825280602002602001820160405280156110bd57816020015b60608152602001906001900390816110a85790505b509250600067ffffffffffffffff8111156110db576110da6124e7565b5b6040519080825280602002602001820160405280156111095781602001602082028036833780820191505090505b509150611302565b6000858261111f9190613677565b905060008186116111305785611132565b815b90508067ffffffffffffffff81111561114e5761114d6124e7565b5b60405190808252806020026020018201604052801561118157816020015b606081526020019060019003908161116c5790505b5094508067ffffffffffffffff81111561119e5761119d6124e7565b5b6040519080825280602002602001820160405280156111cc5781602001602082028036833780820191505090505b50935060005b818110156112fe5760006003828a6111ea9190613a33565b815481106111fb576111fa61350a565b5b90600052602060002001805461121090613568565b80601f016020809104026020016040519081016040528092919081815260200182805461123c90613568565b80156112895780601f1061125e57610100808354040283529160200191611289565b820191906000526020600020905b81548152906001019060200180831161126c57829003601f168201915b50505050509050808783815181106112a4576112a361350a565b5b60200260200101819052506001816040516112bf91906133b7565b9081526020016040518091039020805490508683815181106112e4576112e361350a565b5b6020026020010181815250505080806001019150506111d2565b5050505b9250925092565b600060048260405161131b91906133b7565b908152602001604051809103902060009054906101000a900460ff169050919050565b60608060008060018760405161135491906133b7565b908152602001604051809103902090508080549050915081861061142057600067ffffffffffffffff81111561138d5761138c6124e7565b5b6040519080825280602002602001820160405280156113c057816020015b60608152602001906001900390816113ab5790505b509350600067ffffffffffffffff8111156113de576113dd6124e7565b5b60405190808252806020026020018201604052801561141757816020015b6114046123b0565b8152602001906001900390816113fc5790505b509250506117f4565b6000868361142e9190613677565b9050600081871161143f5786611441565b815b90508067ffffffffffffffff81111561145d5761145c6124e7565b5b60405190808252806020026020018201604052801561149057816020015b606081526020019060019003908161147b5790505b5095508067ffffffffffffffff8111156114ad576114ac6124e7565b5b6040519080825280602002602001820160405280156114e657816020015b6114d36123b0565b8152602001906001900390816114cb5790505b50945060005b818110156117ef57600084828b6115039190613a33565b815481106115145761151361350a565b5b90600052602060002001805461152990613568565b80601f016020809104026020016040519081016040528092919081815260200182805461155590613568565b80156115a25780601f10611577576101008083540402835291602001916115a2565b820191906000526020600020905b81548152906001019060200180831161158557829003601f168201915b50505050509050808883815181106115bd576115bc61350a565b5b602002602001018190525060008b6040516115d891906133b7565b9081526020016040518091039020816040516115f49190613487565b908152602001604051809103902060405180606001604052908160008201805461161d90613568565b80601f016020809104026020016040519081016040528092919081815260200182805461164990613568565b80156116965780601f1061166b57610100808354040283529160200191611696565b820191906000526020600020905b81548152906001019060200180831161167957829003601f168201915b505050505081526020016001820180546116af90613568565b80601f01602080910402602001604051908101604052809291908181526020018280546116db90613568565b80156117285780601f106116fd57610100808354040283529160200191611728565b820191906000526020600020905b81548152906001019060200180831161170b57829003601f168201915b5050505050815260200160028201805461174190613568565b80601f016020809104026020016040519081016040528092919081815260200182805461176d90613568565b80156117ba5780601f1061178f576101008083540402835291602001916117ba565b820191906000526020600020905b81548152906001019060200180831161179d57829003601f168201915b5050505050815250508783815181106117d6576117d561350a565b5b60200260200101819052505080806001019150506114ec565b505050505b93509350939050565b60048160405161180d91906133b7565b908152602001604051809103902060009054906101000a900460ff16611868576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161185f9061342b565b60405180910390fd5b600060018260405161187a91906133b7565b9081526020016040518091039020905060005b8180549050811015611a115760008282815481106118ae576118ad61350a565b5b9060005260206000200180546118c390613568565b80601f01602080910402602001604051908101604052809291908181526020018280546118ef90613568565b801561193c5780601f106119115761010080835404028352916020019161193c565b820191906000526020600020905b81548152906001019060200180831161191f57829003601f168201915b5050505050905060008460405161195391906133b7565b90815260200160405180910390208160405161196f9190613487565b90815260200160405180910390206000808201600061198e9190612370565b60018201600061199e9190612370565b6002820160006119ae9190612370565b505060006002856040516119c291906133b7565b9081526020016040518091039020826040516119de9190613487565b908152602001604051809103902060006101000a81548160ff02191690831515021790555050808060010191505061188d565b50600182604051611a2291906133b7565b90815260200160405180910390206000611a3c91906123d1565b81604051611a4a91906133b7565b60405180910390207f372dd188f66e03080f62fc207ebf4954a98c81128ca2472aedfc273f0f7c788360405160405180910390a25050565b611a8a6123b0565b6000600284604051611a9c91906133b7565b908152602001604051809103902083604051611ab89190613487565b908152602001604051809103902060009054906101000a900460ff1690508015611cda57600084604051611aec91906133b7565b908152602001604051809103902083604051611b089190613487565b9081526020016040518091039020604051806060016040529081600082018054611b3190613568565b80601f0160208091040260200160405190810160405280929190818152602001828054611b5d90613568565b8015611baa5780601f10611b7f57610100808354040283529160200191611baa565b820191906000526020600020905b815481529060010190602001808311611b8d57829003601f168201915b50505050508152602001600182018054611bc390613568565b80601f0160208091040260200160405190810160405280929190818152602001828054611bef90613568565b8015611c3c5780601f10611c1157610100808354040283529160200191611c3c565b820191906000526020600020905b815481529060010190602001808311611c1f57829003601f168201915b50505050508152602001600282018054611c5590613568565b80601f0160208091040260200160405190810160405280929190818152602001828054611c8190613568565b8015611cce5780601f10611ca357610100808354040283529160200191611cce565b820191906000526020600020905b815481529060010190602001808311611cb157829003601f168201915b50505050508152505091505b9250929050565b6000600380549050905090565b6000600182604051611d0091906133b7565b9081526020016040518091039020805490509050919050565b6000600283604051611d2b91906133b7565b908152602001604051809103902082604051611d479190613487565b908152602001604051809103902060009054906101000a900460ff16905092915050565b60005b60038054905081101561204057600060038281548110611d9157611d9061350a565b5b906000526020600020018054611da690613568565b80601f0160208091040260200160405190810160405280929190818152602001828054611dd290613568565b8015611e1f5780601f10611df457610100808354040283529160200191611e1f565b820191906000526020600020905b815481529060010190602001808311611e0257829003601f168201915b505050505090506000600182604051611e3891906133b7565b9081526020016040518091039020905060005b8180549050811015611fcf576000828281548110611e6c57611e6b61350a565b5b906000526020600020018054611e8190613568565b80601f0160208091040260200160405190810160405280929190818152602001828054611ead90613568565b8015611efa5780601f10611ecf57610100808354040283529160200191611efa565b820191906000526020600020905b815481529060010190602001808311611edd57829003601f168201915b50505050509050600084604051611f1191906133b7565b908152602001604051809103902081604051611f2d9190613487565b908152602001604051809103902060008082016000611f4c9190612370565b600182016000611f5c9190612370565b600282016000611f6c9190612370565b50506000600285604051611f8091906133b7565b908152602001604051809103902082604051611f9c9190613487565b908152602001604051809103902060006101000a81548160ff021916908315150217905550508080600101915050611e4b565b50600182604051611fe091906133b7565b90815260200160405180910390206000611ffa91906123d1565b600060048360405161200c91906133b7565b908152602001604051809103902060006101000a81548160ff02191690831515021790555050508080600101915050611d6e565b506003600061204f91906123f2565b7f30addec5e9e954699f286bae8e1558655b0d436c3d7b501014eb5c0b4a76e6db60405160405180910390a1565b60008351116120c1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016120b890613b45565b60405180910390fd5b6000825111612105576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016120fc90613cc9565b60405180910390fd5b60048360405161211591906133b7565b908152602001604051809103902060009054906101000a900460ff166121a2576003839080600181540180825580915050600190039060005260206000200160009091909190915090816121699190613bab565b50600160048460405161217c91906133b7565b908152602001604051809103902060006101000a81548160ff0219169083151502179055505b6002836040516121b291906133b7565b9081526020016040518091039020826040516121ce9190613487565b908152602001604051809103902060009054906101000a900460ff16612293576001836040516121fe91906133b7565b90815260200160405180910390208290806001815401808255809150506001900390600052602060002001600090919091909150908161223e9190613ce9565b50600160028460405161225191906133b7565b90815260200160405180910390208360405161226d9190613487565b908152602001604051809103902060006101000a81548160ff0219169083151502179055505b806000846040516122a491906133b7565b9081526020016040518091039020836040516122c09190613487565b908152602001604051809103902060008201518160000190816122e39190613ce9565b5060208201518160010190816122f99190613ce9565b50604082015181600201908161230f9190613ce9565b50905050816040516123219190613487565b60405180910390208360405161233791906133b7565b60405180910390207fd00871f87cd1b1b4e50e5be511f060478c06a013856673c392f2adbfa65df8ad60405160405180910390a3505050565b50805461237c90613568565b6000825580601f1061238e57506123ad565b601f0160209004906000526020600020908101906123ac9190612413565b5b50565b60405180606001604052806060815260200160608152602001606081525090565b50805460008255906000526020600020908101906123ef9190612430565b50565b50805460008255906000526020600020908101906124109190612454565b50565b5b8082111561242c576000816000905550600101612414565b5090565b5b8082111561245057600081816124479190612370565b50600101612431565b5090565b5b80821115612474576000818161246b9190612478565b50600101612455565b5090565b50805461248490613568565b6000825580601f1061249657506124b5565b601f0160209004906000526020600020908101906124b49190612413565b5b50565b6000604051905090565b600080fd5b600080fd5b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b61251f826124d6565b810181811067ffffffffffffffff8211171561253e5761253d6124e7565b5b80604052505050565b60006125516124b8565b905061255d8282612516565b919050565b600067ffffffffffffffff82111561257d5761257c6124e7565b5b612586826124d6565b9050602081019050919050565b82818337600083830152505050565b60006125b56125b084612562565b612547565b9050828152602081018484840111156125d1576125d06124d1565b5b6125dc848285612593565b509392505050565b600082601f8301126125f9576125f86124cc565b5b81356126098482602086016125a2565b91505092915050565b600067ffffffffffffffff82111561262d5761262c6124e7565b5b612636826124d6565b9050602081019050919050565b600061265661265184612612565b612547565b905082815260208101848484011115612672576126716124d1565b5b61267d848285612593565b509392505050565b600082601f83011261269a576126996124cc565b5b81356126aa848260208601612643565b91505092915050565b600080604083850312156126ca576126c96124c2565b5b600083013567ffffffffffffffff8111156126e8576126e76124c7565b5b6126f4858286016125e4565b925050602083013567ffffffffffffffff811115612715576127146124c7565b5b61272185828601612685565b9150509250929050565b600067ffffffffffffffff821115612746576127456124e7565b5b602082029050602081019050919050565b600080fd5b600061276f61276a8461272b565b612547565b9050808382526020820190506020840283018581111561279257612791612757565b5b835b818110156127d957803567ffffffffffffffff8111156127b7576127b66124cc565b5b8086016127c48982612685565b85526020850194505050602081019050612794565b5050509392505050565b600082601f8301126127f8576127f76124cc565b5b813561280884826020860161275c565b91505092915050565b60008060408385031215612828576128276124c2565b5b600083013567ffffffffffffffff811115612846576128456124c7565b5b612852858286016125e4565b925050602083013567ffffffffffffffff811115612873576128726124c7565b5b61287f858286016127e3565b9150509250929050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b600081519050919050565b600082825260208201905092915050565b60005b838110156128ef5780820151818401526020810190506128d4565b60008484015250505050565b6000612906826128b5565b61291081856128c0565b93506129208185602086016128d1565b612929816124d6565b840191505092915050565b6000606083016000830151848203600086015261295182826128fb565b9150506020830151848203602086015261296b82826128fb565b9150506040830151848203604086015261298582826128fb565b9150508091505092915050565b600061299e8383612934565b905092915050565b6000602082019050919050565b60006129be82612889565b6129c88185612894565b9350836020820285016129da856128a5565b8060005b85811015612a1657848403895281516129f78582612992565b9450612a02836129a6565b925060208a019950506001810190506129de565b50829750879550505050505092915050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b60008115159050919050565b612a6981612a54565b82525050565b6000612a7b8383612a60565b60208301905092915050565b6000602082019050919050565b6000612a9f82612a28565b612aa98185612a33565b9350612ab483612a44565b8060005b83811015612ae5578151612acc8882612a6f565b9750612ad783612a87565b925050600181019050612ab8565b5085935050505092915050565b60006040820190508181036000830152612b0c81856129b3565b90508181036020830152612b208184612a94565b90509392505050565b6000819050919050565b612b3c81612b29565b82525050565b6000602082019050612b576000830184612b33565b92915050565b612b6681612b29565b8114612b7157600080fd5b50565b600081359050612b8381612b5d565b92915050565b600080600060608486031215612ba257612ba16124c2565b5b600084013567ffffffffffffffff811115612bc057612bbf6124c7565b5b612bcc868287016125e4565b9350506020612bdd86828701612b74565b9250506040612bee86828701612b74565b9150509250925092565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b6000612c3083836128fb565b905092915050565b6000602082019050919050565b6000612c5082612bf8565b612c5a8185612c03565b935083602082028501612c6c85612c14565b8060005b85811015612ca85784840389528151612c898582612c24565b9450612c9483612c38565b925060208a01995050600181019050612c70565b50829750879550505050505092915050565b60006040820190508181036000830152612cd48185612c45565b9050612ce36020830184612b33565b9392505050565b600067ffffffffffffffff821115612d0557612d046124e7565b5b602082029050602081019050919050565b600080fd5b600080fd5b600060608284031215612d3657612d35612d16565b5b612d406060612547565b9050600082013567ffffffffffffffff811115612d6057612d5f612d1b565b5b612d6c84828501612685565b600083015250602082013567ffffffffffffffff811115612d9057612d8f612d1b565b5b612d9c84828501612685565b602083015250604082013567ffffffffffffffff811115612dc057612dbf612d1b565b5b612dcc84828501612685565b60408301525092915050565b6000612deb612de684612cea565b612547565b90508083825260208201905060208402830185811115612e0e57612e0d612757565b5b835b81811015612e5557803567ffffffffffffffff811115612e3357612e326124cc565b5b808601612e408982612d20565b85526020850194505050602081019050612e10565b5050509392505050565b600082601f830112612e7457612e736124cc565b5b8135612e84848260208601612dd8565b91505092915050565b600080600060608486031215612ea657612ea56124c2565b5b600084013567ffffffffffffffff811115612ec457612ec36124c7565b5b612ed0868287016125e4565b935050602084013567ffffffffffffffff811115612ef157612ef06124c7565b5b612efd868287016127e3565b925050604084013567ffffffffffffffff811115612f1e57612f1d6124c7565b5b612f2a86828701612e5f565b9150509250925092565b60008060408385031215612f4b57612f4a6124c2565b5b6000612f5985828601612b74565b9250506020612f6a85828601612b74565b9150509250929050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b600081519050919050565b600082825260208201905092915050565b6000612fc782612fa0565b612fd18185612fab565b9350612fe18185602086016128d1565b612fea816124d6565b840191505092915050565b60006130018383612fbc565b905092915050565b6000602082019050919050565b600061302182612f74565b61302b8185612f7f565b93508360208202850161303d85612f90565b8060005b85811015613079578484038952815161305a8582612ff5565b945061306583613009565b925060208a01995050600181019050613041565b50829750879550505050505092915050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b6130c081612b29565b82525050565b60006130d283836130b7565b60208301905092915050565b6000602082019050919050565b60006130f68261308b565b6131008185613096565b935061310b836130a7565b8060005b8381101561313c57815161312388826130c6565b975061312e836130de565b92505060018101905061310f565b5085935050505092915050565b600060608201905081810360008301526131638186613016565b9050818103602083015261317781856130eb565b90506131866040830184612b33565b949350505050565b6000602082840312156131a4576131a36124c2565b5b600082013567ffffffffffffffff8111156131c2576131c16124c7565b5b6131ce848285016125e4565b91505092915050565b6131e081612a54565b82525050565b60006020820190506131fb60008301846131d7565b92915050565b6000606082019050818103600083015261321b8186612c45565b9050818103602083015261322f81856129b3565b905061323e6040830184612b33565b949350505050565b6000606083016000830151848203600086015261326382826128fb565b9150506020830151848203602086015261327d82826128fb565b9150506040830151848203604086015261329782826128fb565b9150508091505092915050565b600060408201905081810360008301526132be8185613246565b90506132cd60208301846131d7565b9392505050565b6000806000606084860312156132ed576132ec6124c2565b5b600084013567ffffffffffffffff81111561330b5761330a6124c7565b5b613317868287016125e4565b935050602084013567ffffffffffffffff811115613338576133376124c7565b5b61334486828701612685565b925050604084013567ffffffffffffffff811115613365576133646124c7565b5b61337186828701612d20565b9150509250925092565b600081905092915050565b600061339182612fa0565b61339b818561337b565b93506133ab8185602086016128d1565b80840191505092915050565b60006133c38284613386565b915081905092915050565b600082825260208201905092915050565b7f4e616d65737061636520646f6573206e6f742065786973740000000000000000600082015250565b60006134156018836133ce565b9150613420826133df565b602082019050919050565b6000602082019050818103600083015261344481613408565b9050919050565b600081905092915050565b6000613461826128b5565b61346b818561344b565b935061347b8185602086016128d1565b80840191505092915050565b60006134938284613456565b915081905092915050565b7f4b657920646f6573206e6f7420657869737420696e206e616d65737061636500600082015250565b60006134d4601f836133ce565b91506134df8261349e565b602082019050919050565b60006020820190508181036000830152613503816134c7565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b6000600282049050600182168061358057607f821691505b60208210810361359357613592613539565b5b50919050565b60008190508160005260206000209050919050565b600081546135bb81613568565b6135c5818661344b565b945060018216600081146135e057600181146135f557613628565b60ff1983168652811515820286019350613628565b6135fe85613599565b60005b8381101561362057815481890152600182019150602081019050613601565b838801955050505b50505092915050565b600061363d82846135ae565b915081905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600061368282612b29565b915061368d83612b29565b92508282039050818111156136a5576136a4613648565b5b92915050565b6000815490506136ba81613568565b9050919050565b60008190508160005260206000209050919050565b60006020601f8301049050919050565b600082821b905092915050565b6000600883026137237fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff826136e6565b61372d86836136e6565b95508019841693508086168417925050509392505050565b6000819050919050565b600061376a61376561376084612b29565b613745565b612b29565b9050919050565b6000819050919050565b6137848361374f565b61379861379082613771565b8484546136f3565b825550505050565b600090565b6137ad6137a0565b6137b881848461377b565b505050565b5b818110156137dc576137d16000826137a5565b6001810190506137be565b5050565b601f821115613821576137f281613599565b6137fb846136d6565b8101602085101561380a578190505b61381e613816856136d6565b8301826137bd565b50505b505050565b600082821c905092915050565b600061384460001984600802613826565b1980831691505092915050565b600061385d8383613833565b9150826002028217905092915050565b81810361387b575050613953565b613884826136ab565b67ffffffffffffffff81111561389d5761389c6124e7565b5b6138a78254613568565b6138b28282856137e0565b6000601f8311600181146138e157600084156138cf578287015490505b6138d98582613851565b86555061394c565b601f1984166138ef876136c1565b96506138fa86613599565b60005b82811015613922578489015482556001820191506001850194506020810190506138fd565b8683101561393f578489015461393b601f891682613833565b8355505b6001600288020188555050505b5050505050505b565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b60008190508160005260206000209050919050565b600081546139a681613568565b6139b0818661337b565b945060018216600081146139cb57600181146139e057613a13565b60ff1983168652811515820286019350613a13565b6139e985613984565b60005b83811015613a0b578154818901526001820191506020810190506139ec565b838801955050505b50505092915050565b6000613a288284613999565b915081905092915050565b6000613a3e82612b29565b9150613a4983612b29565b9250828201905080821115613a6157613a60613648565b5b92915050565b7f4b65797320616e642076616c75657320617272617973206d757374206861766560008201527f2073616d65206c656e6774680000000000000000000000000000000000000000602082015250565b6000613ac3602c836133ce565b9150613ace82613a67565b604082019050919050565b60006020820190508181036000830152613af281613ab6565b9050919050565b7f4e616d6573706163652063616e6e6f7420626520656d70747900000000000000600082015250565b6000613b2f6019836133ce565b9150613b3a82613af9565b602082019050919050565b60006020820190508181036000830152613b5e81613b22565b9050919050565b601f821115613ba657613b7781613984565b613b80846136d6565b81016020851015613b8f578190505b613ba3613b9b856136d6565b8301826137bd565b50505b505050565b613bb482612fa0565b67ffffffffffffffff811115613bcd57613bcc6124e7565b5b613bd78254613568565b613be2828285613b65565b600060209050601f831160018114613c155760008415613c03578287015190505b613c0d8582613851565b865550613c75565b601f198416613c2386613984565b60005b82811015613c4b57848901518255600182019150602085019450602081019050613c26565b86831015613c685784890151613c64601f891682613833565b8355505b6001600288020188555050505b505050505050565b7f4b65792063616e6e6f7420626520656d70747900000000000000000000000000600082015250565b6000613cb36013836133ce565b9150613cbe82613c7d565b602082019050919050565b60006020820190508181036000830152613ce281613ca6565b9050919050565b613cf2826128b5565b67ffffffffffffffff811115613d0b57613d0a6124e7565b5b613d158254613568565b613d208282856137e0565b600060209050601f831160018114613d535760008415613d41578287015190505b613d4b8582613851565b865550613db3565b601f198416613d6186613599565b60005b82811015613d8957848901518255600182019150602085019450602081019050613d64565b86831015613da65784890151613da2601f891682613833565b8355505b6001600288020188555050505b50505050505056fea264697066735822122010e6a669447af75331d35ed4f9d0505114fdea36140b19387ecd7764e89d732064736f6c63430008180033" diff --git a/systemcontracts/systemcontracts.go b/systemcontracts/systemcontracts.go new file mode 100644 index 0000000000..df83219409 --- /dev/null +++ b/systemcontracts/systemcontracts.go @@ -0,0 +1,141 @@ +// Package systemcontracts provides system contract management functionality +package systemcontracts + +import ( + "encoding/hex" + "fmt" + "math/big" + + "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/crypto" + "github.com/iotexproject/go-pkgs/hash" + "github.com/iotexproject/iotex-address/address" + + "github.com/iotexproject/iotex-core/v2/pkg/log" +) + +// SystemContract represents a system contract with its address and bytecode +type SystemContract struct { + Address address.Address + Code []byte +} + +const ( + // StakingBucketsContractIndex is the system contract for staking buckets storage + StakingBucketsContractIndex int = iota + // BucketPoolContractIndex is the system contract for bucket pool storage + BucketPoolContractIndex + // BucketIndicesContractIndex is the system contract for bucket indices storage + BucketIndicesContractIndex + // EndorsementContractIndex is the system contract for endorsement storage + EndorsementContractIndex + // CandidateMapContractIndex is the system contract for candidate map storage + CandidateMapContractIndex + // CandidatesContractIndex is the system contract for candidates storage + CandidatesContractIndex + // PollCandidateListContractIndex is the system contract for poll candidate storage + PollCandidateListContractIndex + // PollLegacyCandidateListContractIndex is the system contract for poll legacy candidate storage + PollLegacyCandidateListContractIndex + // PollProbationListContractIndex is the system contract for poll probation list storage + PollProbationListContractIndex + // PollUnproductiveDelegateContractIndex is the system contract for poll unproductive delegate storage + PollUnproductiveDelegateContractIndex + // PollBlockMetaContractIndex is the system contract for poll block meta storage + PollBlockMetaContractIndex + // RewardingContractV1Index is the system contract for rewarding admin storage + RewardingContractV1Index + // RewardingContractV2Index is the system contract for rewarding admin storage v2 + RewardingContractV2Index + // StakingViewContractIndex is the system contract for staking view storage + StakingViewContractIndex + // SystemContractCount is the total number of system contracts + SystemContractCount +) + +const ( + defaultSystemContractType = iota + namespaceStorageContractType +) + +var systemContractTypes = map[int]int{ + StakingViewContractIndex: namespaceStorageContractType, +} + +// SystemContracts holds all system contracts +var SystemContracts []SystemContract + +var systemContractCreatorAddr = hash.Hash160b([]byte("system_contract_creator")) + +func init() { + initSystemContracts() +} + +// initSystemContracts initializes the system contracts array +func initSystemContracts() { + genericStorageByteCode, err := hex.DecodeString(GenericStorageByteCodeStr) + if err != nil { + log.S().Panic("failed to decode GenericStorageByteCode: " + err.Error()) + } + namespaceStorageByteCode, err := hex.DecodeString(NamespaceStorageContractByteCodeStr) + if err != nil { + log.S().Panic("failed to decode NamespaceStorageContractByteCode: " + err.Error()) + } + + SystemContracts = make([]SystemContract, SystemContractCount) + for i := 0; i < SystemContractCount; i++ { + addr, err := address.FromBytes(crypto.CreateAddress(common.BytesToAddress(systemContractCreatorAddr[:]), uint64(i)).Bytes()) + if err != nil { + log.S().Panic("Invalid system contract address: " + err.Error()) + } + var byteCode []byte + switch systemContractTypes[i] { + case namespaceStorageContractType: + byteCode = namespaceStorageByteCode + default: + byteCode = genericStorageByteCode + } + SystemContracts[i] = SystemContract{ + Address: addr, + Code: byteCode, + } + } +} + +// ContractBackend defines the interface for contract backend operations +type ContractBackend interface { + Call(callMsg *ethereum.CallMsg) ([]byte, error) + Handle(callMsg *ethereum.CallMsg) error +} + +// ContractDeployer defines the interface for contract deployment operations +type ContractDeployer interface { + Deploy(callMsg *ethereum.CallMsg) (address.Address, error) + Exists(addr address.Address) bool +} + +// DeploySystemContractsIfNotExist deploys system contracts if they don't exist +func DeploySystemContractsIfNotExist(deployer ContractDeployer) error { + for idx, contract := range SystemContracts { + exists := deployer.Exists(contract.Address) + if !exists { + log.S().Infof("Deploying system contract [%d] %s", idx, contract.Address.String()) + msg := ðereum.CallMsg{ + From: common.BytesToAddress(systemContractCreatorAddr[:]), + Data: contract.Code, + Value: big.NewInt(0), + Gas: 10000000, + } + if addr, err := deployer.Deploy(msg); err != nil { + return fmt.Errorf("failed to deploy system contract %s: %w", contract.Address.String(), err) + } else if addr.String() != contract.Address.String() { + return fmt.Errorf("deployed contract address %s does not match expected address %s", addr.String(), contract.Address.String()) + } + log.S().Infof("System contract [%d] %s deployed successfully", idx, contract.Address.String()) + } else { + log.S().Infof("System contract [%d] %s already exists", idx, contract.Address.String()) + } + } + return nil +} From 5a99359113ac8dc2584cbb9d70243ca6a8a9d689 Mon Sep 17 00:00:00 2001 From: envestcc Date: Thu, 21 Aug 2025 09:09:52 +0800 Subject: [PATCH 02/26] define state namespaces --- action/protocol/execution/evm/contract.go | 6 +-- action/protocol/protocol.go | 3 +- action/protocol/rewarding/protocol.go | 2 +- action/protocol/staking/protocol.go | 6 +-- state/factory/factory.go | 9 +--- state/tables.go | 61 +++++++++++++++++++++++ 6 files changed, 72 insertions(+), 15 deletions(-) create mode 100644 state/tables.go diff --git a/action/protocol/execution/evm/contract.go b/action/protocol/execution/evm/contract.go index bca8a17e4a..6b0a74a39d 100644 --- a/action/protocol/execution/evm/contract.go +++ b/action/protocol/execution/evm/contract.go @@ -20,11 +20,11 @@ import ( const ( // CodeKVNameSpace is the bucket name for code - CodeKVNameSpace = "Code" + CodeKVNameSpace = state.CodeKVNameSpace // ContractKVNameSpace is the bucket name for contract data storage - ContractKVNameSpace = "Contract" + ContractKVNameSpace = state.ContractKVNameSpace // PreimageKVNameSpace is the bucket name for preimage data storage - PreimageKVNameSpace = "Preimage" + PreimageKVNameSpace = state.PreimageKVNameSpace ) type ( diff --git a/action/protocol/protocol.go b/action/protocol/protocol.go index 39607e1928..7d8d4f4cca 100644 --- a/action/protocol/protocol.go +++ b/action/protocol/protocol.go @@ -16,6 +16,7 @@ import ( "github.com/iotexproject/iotex-core/v2/action" "github.com/iotexproject/iotex-core/v2/pkg/log" + "github.com/iotexproject/iotex-core/v2/state" ) var ( @@ -27,7 +28,7 @@ var ( const ( // SystemNamespace is the namespace to store system information such as candidates/probationList/unproductiveDelegates - SystemNamespace = "System" + SystemNamespace = state.SystemNamespace ) // Protocol defines the protocol interfaces atop IoTeX blockchain diff --git a/action/protocol/rewarding/protocol.go b/action/protocol/rewarding/protocol.go index 258026a731..8375a45ace 100644 --- a/action/protocol/rewarding/protocol.go +++ b/action/protocol/rewarding/protocol.go @@ -28,7 +28,7 @@ import ( const ( // TODO: it works only for one instance per protocol definition now _protocolID = "rewarding" - _v2RewardingNamespace = "Rewarding" + _v2RewardingNamespace = state.RewardingNamespace ) var ( diff --git a/action/protocol/staking/protocol.go b/action/protocol/staking/protocol.go index cb82fd60aa..59d510651d 100644 --- a/action/protocol/staking/protocol.go +++ b/action/protocol/staking/protocol.go @@ -34,13 +34,13 @@ const ( _protocolID = "staking" // _stakingNameSpace is the bucket name for staking state - _stakingNameSpace = "Staking" + _stakingNameSpace = state.StakingNamespace // _candidateNameSpace is the bucket name for candidate state - _candidateNameSpace = "Candidate" + _candidateNameSpace = state.CandidateNamespace // CandsMapNS is the bucket name to store candidate map - CandsMapNS = "CandsMap" + CandsMapNS = state.CandsMapNamespace ) const ( diff --git a/state/factory/factory.go b/state/factory/factory.go index 44c75aa807..ffc913a331 100644 --- a/state/factory/factory.go +++ b/state/factory/factory.go @@ -26,19 +26,14 @@ import ( "github.com/iotexproject/iotex-core/v2/db/trie" "github.com/iotexproject/iotex-core/v2/pkg/lifecycle" "github.com/iotexproject/iotex-core/v2/pkg/prometheustimer" + "github.com/iotexproject/iotex-core/v2/state" ) const ( // AccountKVNamespace is the bucket name for account - AccountKVNamespace = "Account" - // ArchiveNamespacePrefix is the prefix of the buckets storing history data - ArchiveNamespacePrefix = "Archive" + AccountKVNamespace = state.AccountKVNamespace // CurrentHeightKey indicates the key of current factory height in underlying DB CurrentHeightKey = "currentHeight" - // ArchiveTrieNamespace is the bucket for the latest state view - ArchiveTrieNamespace = "AccountTrie" - // ArchiveTrieRootKey indicates the key of accountTrie root hash in underlying DB - ArchiveTrieRootKey = "archiveTrieRoot" ) var ( diff --git a/state/tables.go b/state/tables.go new file mode 100644 index 0000000000..97e9486d84 --- /dev/null +++ b/state/tables.go @@ -0,0 +1,61 @@ +package state + +const ( + // SystemNamespace is the namespace to store system information such as candidates/probationList/unproductiveDelegates + // Poll Protocol uses this namespace to store states: + // - hash256(CurCandidateKey/NextCandidateKey) --> CandidatesList + // - hash256(CurProbationKey/NextProbationKey) --> ProbationList + // - hash256(UnproductiveDelegatesKey) --> UnproductiveDelegates + // - hash256(BlockMetaPrefix)+height%heightInEpoch --> BlockMeta + SystemNamespace = "System" + + // AccountKVNamespace is the bucket name for account + // Poll Protocol uses this namespace to store LEGACY states: + // - hash160(CandidatesPrefix+height) --> CandidatesList + // Rewarding Protocol uses this namespace to store LEGACY states: + // - hash160(hash160(rewarding)+adminKey) --> admin + // - hash160(hash160(rewarding)+exemptKey) --> exempt + // - hash160(hash160(rewarding)+fundKey) --> fund + // - hash160(hash160(rewarding)+_blockRewardHistoryKeyPrefix+height) --> rewardHistory + // - hash160(hash160(rewarding)+_epochRewardHistoryKeyPrefix+epoch) --> rewardHistory + // - hash160(hash160(rewarding)+adminKey+address) --> rewardAccount + AccountKVNamespace = "Account" + + // RewardingNamespace is the namespace to store rewarding information + // - hash160(rewarding)+adminKey --> admin + // - hash160(rewarding)+exemptKey --> exempt + // - hash160(rewarding)+fundKey --> fund + // - hash160(rewarding)+_blockRewardHistoryKeyPrefix+height --> rewardHistory + // - hash160(rewarding)+_epochRewardHistoryKeyPrefix+epoch --> rewardHistory + // - hash160(rewarding)+adminKey+address --> rewardAccount + RewardingNamespace = "Rewarding" + + // StakingNamespace is the namespace to store staking information + // - "0" + totalBucketKey --> totalBucketCount + // - "1" + --> VoteBucket + // - "2" + --> BucketIndices + // - "3" + --> BucketIndices + // - "4" + --> Endorsement + StakingNamespace = "Staking" + + // CandidateNamespace is the namespace to store candidate information + // - --> Candidate + CandidateNamespace = "Candidate" + + // CandsMapNamespace is the namespace to store candidate map + // - "name" --> CandidateList + // - "operator" --> CandidateList + // - "owner" --> CandidateList + CandsMapNamespace = "CandsMap" + + // CodeKVNameSpace is the bucket name for code + // codeHash --> code + CodeKVNameSpace = "Code" + + // ContractKVNameSpace is the bucket name for contract data storage + // trieKey --> trieValue + ContractKVNameSpace = "Contract" + + // PreimageKVNameSpace is the bucket name for preimage data storage + PreimageKVNameSpace = "Preimage" +) From ab32d0190d1d0c5411fc63eaf0969d3172a6ab97 Mon Sep 17 00:00:00 2001 From: envestcc Date: Thu, 21 Aug 2025 09:14:38 +0800 Subject: [PATCH 03/26] contract backend --- action/protocol/execution/evm/evm.go | 20 +- state/factory/contract_backend.go | 272 +++++++++++++++++++++++++++ 2 files changed, 288 insertions(+), 4 deletions(-) create mode 100644 state/factory/contract_backend.go diff --git a/action/protocol/execution/evm/evm.go b/action/protocol/execution/evm/evm.go index 4623d49e82..08da1c89aa 100644 --- a/action/protocol/execution/evm/evm.go +++ b/action/protocol/execution/evm/evm.go @@ -8,6 +8,7 @@ package evm import ( "bytes" "context" + "encoding/hex" "math" "math/big" "time" @@ -326,10 +327,7 @@ func ExecuteContract( if ps.featureCtx.SetRevertMessageToReceipt && receipt.Status == uint64(iotextypes.ReceiptStatus_ErrExecutionReverted) && retval != nil && bytes.Equal(retval[:4], _revertSelector) { // in case of the execution revert error, parse the retVal and add to receipt - data := retval[4:] - msgLength := byteutil.BytesToUint64BigEndian(data[56:64]) - revertMsg := string(data[64 : 64+msgLength]) - receipt.SetExecutionRevertMsg(revertMsg) + receipt.SetExecutionRevertMsg(ExtractRevertMessage(retval)) } log.S().Debugf("Retval: %x, Receipt: %+v, %v", retval, receipt, err) if tCtx, ok := GetTracerCtx(ctx); ok && tCtx.CaptureTx != nil { @@ -765,3 +763,17 @@ func SimulateExecution( )) return ExecuteContract(ctx, sm, ex) } + +// ExtractRevertMessage extracts the revert message from the return value +func ExtractRevertMessage(ret []byte) string { + if len(ret) < 4 { + return hex.EncodeToString(ret) + } + if !bytes.Equal(ret[:4], _revertSelector) { + return hex.EncodeToString(ret) + } + data := ret[4:] + msgLength := byteutil.BytesToUint64BigEndian(data[56:64]) + revertMsg := string(data[64 : 64+msgLength]) + return revertMsg +} diff --git a/state/factory/contract_backend.go b/state/factory/contract_backend.go new file mode 100644 index 0000000000..a6ce741daf --- /dev/null +++ b/state/factory/contract_backend.go @@ -0,0 +1,272 @@ +package factory + +import ( + "context" + "encoding/hex" + "math" + "math/big" + "time" + + "github.com/erigontech/erigon-lib/chain" + erigonComm "github.com/erigontech/erigon-lib/common" + erigonstate "github.com/erigontech/erigon/core/state" + erigonAcc "github.com/erigontech/erigon/core/types/accounts" + "github.com/erigontech/erigon/core/vm" + "github.com/erigontech/erigon/core/vm/evmtypes" + "github.com/ethereum/go-ethereum" + "github.com/holiman/uint256" + "github.com/pkg/errors" + "go.uber.org/zap" + + "github.com/iotexproject/iotex-address/address" + + "github.com/iotexproject/iotex-core/v2/action/protocol" + "github.com/iotexproject/iotex-core/v2/action/protocol/execution/evm" + iotexevm "github.com/iotexproject/iotex-core/v2/action/protocol/execution/evm" + "github.com/iotexproject/iotex-core/v2/blockchain/genesis" + "github.com/iotexproject/iotex-core/v2/pkg/log" +) + +type ( + contractBacked struct { + intraBlockState *erigonstate.IntraBlockState + org erigonstate.StateReader + + // helper fields + height uint64 + timestamp time.Time + g *genesis.Genesis + evmNetworkID uint32 + } +) + +func NewContractBackend(intraBlockState *erigonstate.IntraBlockState, org erigonstate.StateReader, height uint64, timestamp time.Time, g *genesis.Genesis, evmNetworkID uint32) *contractBacked { + return &contractBacked{ + intraBlockState: intraBlockState, + org: org, + height: height, + timestamp: timestamp, + g: g, + evmNetworkID: evmNetworkID, + } +} + +func (backend *contractBacked) Call(callMsg *ethereum.CallMsg) ([]byte, error) { + return backend.call(callMsg, erigonstate.New(&intraStateReader{backend.intraBlockState, backend.org})) +} + +func (backend *contractBacked) Handle(callMsg *ethereum.CallMsg) error { + _, err := backend.call(callMsg, backend.intraBlockState) + return err +} + +func (backend *contractBacked) Deploy(callMsg *ethereum.CallMsg) (address.Address, error) { + evm, err := backend.prepare(backend.intraBlockState) + if err != nil { + return nil, errors.Wrap(err, "failed to prepare EVM for contract deployment") + } + ret, addr, leftGas, err := evm.Create(vm.AccountRef(callMsg.From), callMsg.Data, callMsg.Gas, uint256.MustFromBig(callMsg.Value), true) + if err != nil { + if errors.Is(err, vm.ErrExecutionReverted) { + revertMsg := iotexevm.ExtractRevertMessage(ret) + log.L().Error("EVM deployment reverted", + zap.String("from", callMsg.From.String()), + zap.String("data", hex.EncodeToString(callMsg.Data)), + zap.String("revertMessage", revertMsg), + zap.String("returnData", hex.EncodeToString(ret)), + ) + return nil, errors.Wrapf(err, "deployment reverted: %s", revertMsg) + } + return nil, errors.Wrap(err, "failed to deploy contract") + } + log.L().Info("EVM deployment result", + zap.String("from", callMsg.From.String()), + zap.String("data", hex.EncodeToString(callMsg.Data)), + zap.String("ret", hex.EncodeToString(ret)), + zap.String("address", addr.String()), + zap.Uint64("gasLeft", leftGas), + ) + + return address.FromBytes(addr.Bytes()) +} + +func (backend *contractBacked) Exists(addr address.Address) bool { + return backend.intraBlockState.Exist(erigonComm.BytesToAddress(addr.Bytes())) +} + +func (backend *contractBacked) prepare(intra evmtypes.IntraBlockState) (*vm.EVM, error) { + + // deploy system contracts + blkCtxE := evmtypes.BlockContext{ + CanTransfer: func(state evmtypes.IntraBlockState, addr erigonComm.Address, amount *uint256.Int) bool { + log.L().Debug("CanTransfer called in erigon genesis state creation", + zap.String("address", addr.String()), + zap.String("amount", amount.String()), + ) + return true + }, + Transfer: func(state evmtypes.IntraBlockState, from erigonComm.Address, to erigonComm.Address, amount *uint256.Int, bailout bool) { + log.L().Debug("Transfer called in erigon genesis state creation", + zap.String("from", from.String()), + zap.String("to", to.String()), + zap.String("amount", amount.String()), + ) + return + }, + GetHash: func(block uint64) erigonComm.Hash { + log.L().Debug("GetHash called in erigon genesis state creation", + zap.Uint64("block", block), + ) + return erigonComm.Hash{} + }, + PostApplyMessage: func(ibs evmtypes.IntraBlockState, sender erigonComm.Address, coinbase erigonComm.Address, result *evmtypes.ExecutionResult) { + log.L().Debug("PostApplyMessage called in erigon genesis state creation", + zap.String("sender", sender.String()), + zap.String("coinbase", coinbase.String()), + ) + return + }, + Coinbase: erigonComm.Address{}, + GasLimit: math.MaxUint64, + MaxGasLimit: true, + BlockNumber: backend.height, + Time: uint64(backend.timestamp.Unix()), + Difficulty: big.NewInt(50), + BaseFee: nil, + PrevRanDao: nil, + BlobBaseFee: nil, + } + txCtxE := evmtypes.TxContext{ + TxHash: erigonComm.Hash{}, + Origin: erigonComm.Address{}, + GasPrice: uint256.NewInt(0), + BlobFee: nil, + BlobHashes: nil, + } + ctx := protocol.WithBlockCtx(context.Background(), protocol.BlockCtx{ + BlockHeight: backend.height, + BlockTimeStamp: backend.timestamp}) + ctx = genesis.WithGenesisContext(ctx, *backend.g) + ctx = protocol.WithBlockchainCtx(ctx, protocol.BlockchainCtx{ + GetBlockTime: func(u uint64) (time.Time, error) { + interval := 2500 * time.Millisecond + return backend.timestamp.Add(interval * time.Duration(u-backend.height)), nil + }, + EvmNetworkID: backend.evmNetworkID, + }) + chainCfg, err := evm.NewChainConfig(ctx) + if err != nil { + return nil, errors.Wrap(err, "failed to create chain config") + } + var ( + shanghaiTime *big.Int + cancunTime *big.Int + ) + if chainCfg.ShanghaiTime != nil { + shanghaiTime = big.NewInt(int64(*chainCfg.ShanghaiTime)) + } + if chainCfg.CancunTime != nil { + cancunTime = big.NewInt(int64(*chainCfg.CancunTime)) + } + chainConfig := &chain.Config{ + HomesteadBlock: chainCfg.ConstantinopleBlock, + DAOForkBlock: chainCfg.ConstantinopleBlock, + TangerineWhistleBlock: chainCfg.ConstantinopleBlock, + SpuriousDragonBlock: chainCfg.ConstantinopleBlock, + ByzantiumBlock: chainCfg.ConstantinopleBlock, + ConstantinopleBlock: chainCfg.ConstantinopleBlock, + PetersburgBlock: chainCfg.PetersburgBlock, + IstanbulBlock: chainCfg.IstanbulBlock, + MuirGlacierBlock: chainCfg.MuirGlacierBlock, + BerlinBlock: chainCfg.BerlinBlock, + LondonBlock: chainCfg.LondonBlock, + ArrowGlacierBlock: chainCfg.ArrowGlacierBlock, + GrayGlacierBlock: chainCfg.GrayGlacierBlock, + + ShanghaiTime: shanghaiTime, + CancunTime: cancunTime, + } + vmConfig := vm.Config{ + NoBaseFee: true, + } + evm := vm.NewEVM(blkCtxE, txCtxE, intra, chainConfig, vmConfig) + return evm, nil +} + +func (backend *contractBacked) call(callMsg *ethereum.CallMsg, intra evmtypes.IntraBlockState) ([]byte, error) { + evm, err := backend.prepare(intra) + if err != nil { + return nil, errors.Wrap(err, "failed to prepare EVM for contract call") + } + t := time.Now() + ret, gasLeft, err := evm.Call(vm.AccountRef(callMsg.From), erigonComm.Address(*callMsg.To), callMsg.Data, callMsg.Gas, uint256.MustFromBig(callMsg.Value), true) + if err != nil { + // Check if it's a revert error and extract the revert message + if errors.Is(err, vm.ErrExecutionReverted) { + revertMsg := iotexevm.ExtractRevertMessage(ret) + log.L().Error("EVM call reverted", + zap.String("from", callMsg.From.String()), + zap.String("to", callMsg.To.String()), + zap.Uint64("dataSize", uint64(len(callMsg.Data))), + zap.String("revertMessage", revertMsg), + zap.String("returnData", hex.EncodeToString(ret)), + ) + return ret, errors.Wrapf(err, "execution reverted: %s", revertMsg) + } + return ret, errors.Wrapf(err, "error when system contract %x action mutates states", callMsg.To.Bytes()) + } + log.L().Info("EVM call result", + zap.String("from", callMsg.From.String()), + zap.String("to", callMsg.To.String()), + zap.Uint64("dataSize", uint64(len(callMsg.Data))), + zap.String("ret", hex.EncodeToString(ret)), + zap.Uint64("gasUsed", callMsg.Gas-gasLeft), + zap.Duration("duration", time.Since(t)), + ) + return ret, nil +} + +type intraStateReader struct { + intra *erigonstate.IntraBlockState + org erigonstate.StateReader +} + +func (sr *intraStateReader) ReadAccountData(address erigonComm.Address) (*erigonAcc.Account, error) { + org, err := sr.org.ReadAccountData(address) + if err != nil { + return nil, errors.Wrapf(err, "failed to read account data for address %s", address.String()) + } + acc := &erigonAcc.Account{ + Initialised: false, + Nonce: sr.intra.GetNonce(address), + Balance: *sr.intra.GetBalance(address), + Root: erigonComm.Hash{}, + CodeHash: sr.intra.GetCodeHash(address), + Incarnation: sr.intra.GetIncarnation(address), + PrevIncarnation: 0, + } + if org != nil { + acc.Initialised = org.Initialised + acc.Root = org.Root + acc.PrevIncarnation = org.PrevIncarnation + } + return acc, nil +} + +func (sr *intraStateReader) ReadAccountStorage(address erigonComm.Address, incarnation uint64, key *erigonComm.Hash) ([]byte, error) { + value := new(uint256.Int) + sr.intra.GetState(address, key, value) + return value.Bytes(), nil +} + +func (sr *intraStateReader) ReadAccountCode(address erigonComm.Address, incarnation uint64, codeHash erigonComm.Hash) ([]byte, error) { + code := sr.intra.GetCode(address) + return code, nil +} +func (sr *intraStateReader) ReadAccountCodeSize(address erigonComm.Address, incarnation uint64, codeHash erigonComm.Hash) (int, error) { + return len(sr.intra.GetCode(address)), nil +} + +func (sr *intraStateReader) ReadAccountIncarnation(address erigonComm.Address) (uint64, error) { + return sr.intra.GetIncarnation(address), nil +} From 84d4c14b055480221d3ba6e7b032e131a6caa053 Mon Sep 17 00:00:00 2001 From: envestcc Date: Thu, 21 Aug 2025 09:59:08 +0800 Subject: [PATCH 04/26] contract storage --- state/contract_storage.go | 26 ++++++ state/contract_storage_namespaced.go | 133 +++++++++++++++++++++++++++ state/contract_storage_standard.go | 127 +++++++++++++++++++++++++ 3 files changed, 286 insertions(+) create mode 100644 state/contract_storage.go create mode 100644 state/contract_storage_namespaced.go create mode 100644 state/contract_storage_standard.go diff --git a/state/contract_storage.go b/state/contract_storage.go new file mode 100644 index 0000000000..889e95c74e --- /dev/null +++ b/state/contract_storage.go @@ -0,0 +1,26 @@ +package state + +import ( + "github.com/iotexproject/iotex-address/address" + + "github.com/iotexproject/iotex-core/v2/systemcontracts" +) + +type ContractStorage interface { + StoreToContract(ns string, key []byte, backend systemcontracts.ContractBackend) error + LoadFromContract(ns string, key []byte, backend systemcontracts.ContractBackend) error + DeleteFromContract(ns string, key []byte, backend systemcontracts.ContractBackend) error + ListFromContract(ns string, backend systemcontracts.ContractBackend) ([][]byte, []any, error) + BatchFromContract(ns string, keys [][]byte, backend systemcontracts.ContractBackend) ([]any, error) +} + +type ContractStorageStandard interface { + ContractStorageAddress(ns string, key []byte) (address.Address, error) + New() ContractStorageStandard + Serialize() ([]byte, error) + Deserialize([]byte) error +} + +type ContractStorageProxy interface { + ContractStorageProxy() ContractStorage +} diff --git a/state/contract_storage_namespaced.go b/state/contract_storage_namespaced.go new file mode 100644 index 0000000000..f244dc0390 --- /dev/null +++ b/state/contract_storage_namespaced.go @@ -0,0 +1,133 @@ +package state + +import ( + "math/big" + + "github.com/ethereum/go-ethereum/common" + "github.com/pkg/errors" + + "github.com/iotexproject/iotex-core/v2/pkg/log" + "github.com/iotexproject/iotex-core/v2/systemcontracts" +) + +type contractStorageNamespacedWrapper struct { + standard ContractStorageStandard +} + +// NewContractStorageNamespacedWrapper creates a new ContractStorage wrapper for namespaced storage +func NewContractStorageNamespacedWrapper(standard ContractStorageStandard) ContractStorage { + return &contractStorageNamespacedWrapper{standard: standard} +} + +func (cs *contractStorageNamespacedWrapper) StoreToContract(ns string, key []byte, backend systemcontracts.ContractBackend) error { + contract, err := cs.storageContract(ns, key, backend) + if err != nil { + return err + } + data, err := cs.standard.Serialize() + if err != nil { + return errors.Wrap(err, "failed to serialize storage standard") + } + if err := contract.Put(ns, key, systemcontracts.NamespaceGenericValue{PrimaryData: data}); err != nil { + return errors.Wrapf(err, "failed to store storage standard to contract %s", contract.Address().Hex()) + } + log.S().Infof("Stored storage standard to contract %s with key %x, value: %+v", contract.Address().Hex(), key, cs.standard) + return nil +} + +func (cs *contractStorageNamespacedWrapper) LoadFromContract(ns string, key []byte, backend systemcontracts.ContractBackend) error { + contract, err := cs.storageContract(ns, key, backend) + if err != nil { + return err + } + value, err := contract.Get(ns, key) + if err != nil { + return errors.Wrapf(err, "failed to get storage standard from contract %s with key %x", contract.Address().Hex(), key) + } + if !value.KeyExists { + return errors.Wrapf(ErrStateNotExist, "storage standard does not exist in contract %s with key %x", contract.Address().Hex(), key) + } + if err := cs.standard.Deserialize(value.Value.PrimaryData); err != nil { + return errors.Wrap(err, "failed to deserialize storage standard") + } + log.S().Infof("Loaded storage standard from contract %s with key %x, value: %+v", contract.Address().Hex(), key, cs.standard) + return nil +} + +func (cs *contractStorageNamespacedWrapper) DeleteFromContract(ns string, key []byte, backend systemcontracts.ContractBackend) error { + contract, err := cs.storageContract(ns, key, backend) + if err != nil { + return err + } + if err := contract.Remove(ns, key); err != nil { + return errors.Wrapf(err, "failed to delete storage standard from contract %s with key %x", contract.Address().Hex(), key) + } + log.S().Infof("Deleted storage standard from contract %s with key %x", contract.Address().Hex(), key) + return nil +} + +func (cs *contractStorageNamespacedWrapper) ListFromContract(ns string, backend systemcontracts.ContractBackend) ([][]byte, []any, error) { + contract, err := cs.storageContract(ns, nil, backend) + if err != nil { + return nil, nil, err + } + count, err := contract.CountInNamespace(ns) + if err != nil { + return nil, nil, errors.Wrapf(err, "failed to count storage standards in contract %s", contract.Address().Hex()) + } + if count.Sign() == 0 { + return nil, nil, nil + } + listResult, err := contract.List(ns, big.NewInt(0), count) + if err != nil { + return nil, nil, errors.Wrapf(err, "failed to list storage standards from contract %s", contract.Address().Hex()) + } + log.S().Infof("Listed storage standards from contract %s with keys %v", contract.Address().Hex(), listResult.KeyList) + var indices []any + for _, value := range listResult.Values { + bi := cs.standard.New() + if err := bi.Deserialize(value.PrimaryData); err != nil { + return nil, nil, errors.Wrapf(err, "failed to deserialize storage standard from contract %s", contract.Address().Hex()) + } + indices = append(indices, bi) + } + log.S().Debugf("Listed %d storage standards from contract %s", len(indices), contract.Address().Hex()) + return listResult.KeyList, indices, nil +} + +func (cs *contractStorageNamespacedWrapper) BatchFromContract(ns string, keys [][]byte, backend systemcontracts.ContractBackend) ([]any, error) { + contract, err := cs.storageContract(ns, nil, backend) + if err != nil { + return nil, err + } + storeResult, err := contract.BatchGet(ns, keys) + if err != nil { + return nil, errors.Wrap(err, "failed to batch get storage standards from contract") + } + results := make([]any, 0, len(storeResult.Values)) + for i, value := range storeResult.Values { + if !storeResult.ExistsFlags[i] { + results = append(results, nil) + continue + } + res := cs.standard.New() + if err := res.Deserialize(value.PrimaryData); err != nil { + return nil, errors.Wrapf(err, "failed to deserialize storage standard %x", keys[i]) + } + results = append(results, res) + } + log.S().Infof("Batch loaded %d storage standard from contract %s with keys %d", len(results), contract.Address().Hex(), len(keys)) + return results, nil +} + +func (cs *contractStorageNamespacedWrapper) storageContract(ns string, key []byte, backend systemcontracts.ContractBackend) (*systemcontracts.NamespaceStorageContract, error) { + addr, err := cs.standard.ContractStorageAddress(ns, key) + if err != nil { + return nil, err + } + contract, err := systemcontracts.NewNamespaceStorageContract(common.BytesToAddress(addr.Bytes()), backend) + if err != nil { + return nil, errors.Wrapf(err, "failed to create block meta storage contract") + } + return contract, nil +} diff --git a/state/contract_storage_standard.go b/state/contract_storage_standard.go new file mode 100644 index 0000000000..b2037b32a0 --- /dev/null +++ b/state/contract_storage_standard.go @@ -0,0 +1,127 @@ +package state + +import ( + "github.com/ethereum/go-ethereum/common" + "github.com/pkg/errors" + + "github.com/iotexproject/iotex-core/v2/pkg/log" + "github.com/iotexproject/iotex-core/v2/systemcontracts" +) + +type contractStorageStandardWrapper struct { + standard ContractStorageStandard +} + +func NewContractStorageStandardWrapper(standard ContractStorageStandard) ContractStorage { + return &contractStorageStandardWrapper{standard: standard} +} + +func (cs *contractStorageStandardWrapper) StoreToContract(ns string, key []byte, backend systemcontracts.ContractBackend) error { + contract, err := cs.storageContract(ns, key, backend) + if err != nil { + return err + } + data, err := cs.standard.Serialize() + if err != nil { + return errors.Wrap(err, "failed to serialize storage standard") + } + if err := contract.Put(key, systemcontracts.GenericValue{PrimaryData: data}); err != nil { + return errors.Wrapf(err, "failed to store storage standard to contract %s", contract.Address().Hex()) + } + return nil +} + +func (cs *contractStorageStandardWrapper) LoadFromContract(ns string, key []byte, backend systemcontracts.ContractBackend) error { + contract, err := cs.storageContract(ns, key, backend) + if err != nil { + return err + } + value, err := contract.Get(key) + if err != nil { + return errors.Wrapf(err, "failed to get storage standard from contract %s with key %x", contract.Address().Hex(), key) + } + if !value.KeyExists { + return errors.Wrapf(ErrStateNotExist, "storage standard does not exist in contract %s with key %x", contract.Address().Hex(), key) + } + if err := cs.standard.Deserialize(value.Value.PrimaryData); err != nil { + return errors.Wrap(err, "failed to deserialize storage standard") + } + return nil +} + +func (cs *contractStorageStandardWrapper) DeleteFromContract(ns string, key []byte, backend systemcontracts.ContractBackend) error { + contract, err := cs.storageContract(ns, key, backend) + if err != nil { + return err + } + if err := contract.Remove(key); err != nil { + return errors.Wrapf(err, "failed to delete storage standard from contract %s with key %x", contract.Address().Hex(), key) + } + return nil +} + +func (cs *contractStorageStandardWrapper) ListFromContract(ns string, backend systemcontracts.ContractBackend) ([][]byte, []any, error) { + contract, err := cs.storageContract(ns, nil, backend) + if err != nil { + return nil, nil, err + } + count, err := contract.Count() + if err != nil { + return nil, nil, errors.Wrapf(err, "failed to count storage standards in contract %s", contract.Address().Hex()) + } + if count.Sign() == 0 { + return nil, nil, nil + } + listResult, err := contract.List(0, count.Uint64()) + if err != nil { + return nil, nil, errors.Wrapf(err, "failed to list storage standards from contract %s", contract.Address().Hex()) + } + log.S().Debugf("Listed storage standards from contract %s with keys %v", contract.Address().Hex(), listResult.KeyList) + var indices []any + for _, value := range listResult.Values { + bi := cs.standard.New() + if err := bi.Deserialize(value.PrimaryData); err != nil { + return nil, nil, errors.Wrapf(err, "failed to deserialize storage standard from contract %s", contract.Address().Hex()) + } + indices = append(indices, bi) + } + log.S().Debugf("Listed %d storage standards from contract %s", len(indices), contract.Address().Hex()) + return listResult.KeyList, indices, nil +} + +func (cs *contractStorageStandardWrapper) BatchFromContract(ns string, keys [][]byte, backend systemcontracts.ContractBackend) ([]any, error) { + contract, err := cs.storageContract(ns, nil, backend) + if err != nil { + return nil, err + } + storeResult, err := contract.BatchGet(keys) + if err != nil { + return nil, errors.Wrap(err, "failed to batch get storage standards from contract") + } + results := make([]any, 0, len(storeResult.Values)) + for i, value := range storeResult.Values { + if !storeResult.ExistsFlags[i] { + results = append(results, nil) + continue + } + res := cs.standard.New() + if err := res.Deserialize(value.PrimaryData); err != nil { + return nil, errors.Wrapf(err, "failed to deserialize storage standard %x", keys[i]) + } + results = append(results, res) + } + log.S().Debugf("Batch loaded %d storage standard from contract %s with keys %d", len(results), contract.Address().Hex(), len(keys)) + return results, nil +} + +func (cs *contractStorageStandardWrapper) storageContract(ns string, key []byte, backend systemcontracts.ContractBackend) (*systemcontracts.GenericStorageContract, error) { + addr, err := cs.standard.ContractStorageAddress(ns, key) + if err != nil { + return nil, err + } + contract, err := systemcontracts.NewGenericStorageContract(common.BytesToAddress(addr.Bytes()), backend) + if err != nil { + return nil, errors.Wrapf(err, "failed to create block meta storage contract") + } + return contract, nil +} From 35c797eb7c80c83748c4d1774725e74afd967d6d Mon Sep 17 00:00:00 2001 From: envestcc Date: Thu, 21 Aug 2025 09:59:51 +0800 Subject: [PATCH 05/26] workingset object store --- action/protocol/managers.go | 9 ++ state/factory/workingset.go | 19 ++- state/factory/workingsetstore.go | 44 ++++++- state/factory/workingsetstore_erigon.go | 116 +++++++++++++++++- .../workingsetstore_erigon_simulate.go | 27 +++- state/factory/workingsetstore_test.go | 4 +- .../factory/workingsetstore_with_secondary.go | 35 +++++- 7 files changed, 233 insertions(+), 21 deletions(-) diff --git a/action/protocol/managers.go b/action/protocol/managers.go index edca9796c9..7b24c616c6 100644 --- a/action/protocol/managers.go +++ b/action/protocol/managers.go @@ -54,12 +54,21 @@ func CreateStateConfig(opts ...StateOption) (*StateConfig, error) { return &cfg, nil } +// ObjectOption sets the object for call +func ObjectOption(obj any) StateOption { + return func(cfg *StateConfig) error { + cfg.Object = obj + return nil + } +} + type ( // StateConfig is the config for accessing stateDB StateConfig struct { Namespace string // namespace used by state's storage Key []byte Keys [][]byte + Object any // object used by state's storage } // StateOption sets parameter for access state diff --git a/state/factory/workingset.go b/state/factory/workingset.go index 38b08b12b7..30ca383d5c 100644 --- a/state/factory/workingset.go +++ b/state/factory/workingset.go @@ -336,11 +336,7 @@ func (ws *workingSet) State(s interface{}, opts ...protocol.StateOption) (uint64 if cfg.Keys != nil { return 0, errors.Wrap(ErrNotSupported, "Read state with keys option has not been implemented yet") } - value, err := ws.store.Get(cfg.Namespace, cfg.Key) - if err != nil { - return ws.height, err - } - return ws.height, state.Deserialize(s, value) + return ws.height, ws.store.GetObject(cfg.Namespace, cfg.Key, s) } func (ws *workingSet) States(opts ...protocol.StateOption) (uint64, state.Iterator, error) { @@ -351,7 +347,7 @@ func (ws *workingSet) States(opts ...protocol.StateOption) (uint64, state.Iterat if cfg.Key != nil { return 0, nil, errors.Wrap(ErrNotSupported, "Read states with key option has not been implemented yet") } - keys, values, err := ws.store.States(cfg.Namespace, cfg.Keys) + keys, values, err := ws.store.States(cfg.Namespace, cfg.Keys, cfg.Object) if err != nil { return 0, nil, err } @@ -369,11 +365,7 @@ func (ws *workingSet) PutState(s interface{}, opts ...protocol.StateOption) (uin if err != nil { return ws.height, err } - ss, err := state.Serialize(s) - if err != nil { - return ws.height, errors.Wrapf(err, "failed to convert account %v to bytes", s) - } - return ws.height, ws.store.Put(cfg.Namespace, cfg.Key, ss) + return ws.height, ws.store.PutObject(cfg.Namespace, cfg.Key, s) } // DelState deletes a state from DB @@ -383,7 +375,7 @@ func (ws *workingSet) DelState(opts ...protocol.StateOption) (uint64, error) { if err != nil { return ws.height, err } - return ws.height, ws.store.Delete(cfg.Namespace, cfg.Key) + return ws.height, ws.store.DeleteObject(cfg.Namespace, cfg.Key, cfg.Object) } // ReadView reads the view @@ -399,6 +391,9 @@ func (ws *workingSet) WriteView(name string, v protocol.View) error { // CreateGenesisStates initialize the genesis states func (ws *workingSet) CreateGenesisStates(ctx context.Context) error { + if err := ws.store.CreateGenesisStates(ctx); err != nil { + return err + } if reg, ok := protocol.GetRegistry(ctx); ok { for _, p := range reg.All() { if gsc, ok := p.(protocol.GenesisStateCreator); ok { diff --git a/state/factory/workingsetstore.go b/state/factory/workingsetstore.go index 7c2651c781..57b546ee5c 100644 --- a/state/factory/workingsetstore.go +++ b/state/factory/workingsetstore.go @@ -22,8 +22,11 @@ import ( type ( workingSetStore interface { db.KVStore + PutObject(ns string, key []byte, object any) (err error) + GetObject(ns string, key []byte, object any) error + DeleteObject(ns string, key []byte, object any) error + States(ns string, keys [][]byte, object any) ([][]byte, [][]byte, error) Commit(context.Context, uint64) error - States(string, [][]byte) ([][]byte, [][]byte, error) Digest() hash.Hash256 Finalize(context.Context) error FinalizeTx(context.Context) error @@ -31,6 +34,7 @@ type ( RevertSnapshot(int) error ResetSnapshots() Close() + CreateGenesisStates(context.Context) error } stateDBWorkingSetStore struct { @@ -65,7 +69,23 @@ func (store *stateDBWorkingSetStore) WriteBatch(bat batch.KVStoreBatch) error { return store.flusher.Flush() } +func (store *stateDBWorkingSetStore) PutObject(ns string, key []byte, obj any) error { + store.lock.Lock() + defer store.lock.Unlock() + value, err := state.Serialize(obj) + if err != nil { + return errors.Wrapf(err, "failed to serialize object of ns = %x and key = %x", ns, key) + } + return store.putKV(ns, key, value) +} + func (store *stateDBWorkingSetStore) Put(ns string, key []byte, value []byte) error { + store.lock.Lock() + defer store.lock.Unlock() + return store.putKV(ns, key, value) +} + +func (store *stateDBWorkingSetStore) putKV(ns string, key []byte, value []byte) error { store.lock.Lock() defer store.lock.Unlock() if err := store.flusher.KVStoreWithBuffer().Put(ns, key, value); err != nil { @@ -77,6 +97,10 @@ func (store *stateDBWorkingSetStore) Put(ns string, key []byte, value []byte) er return store.flusher.Flush() } +func (store *stateDBWorkingSetStore) DeleteObject(ns string, key []byte, obj any) error { + return store.Delete(ns, key) +} + func (store *stateDBWorkingSetStore) Delete(ns string, key []byte) error { store.lock.Lock() defer store.lock.Unlock() @@ -127,7 +151,19 @@ func (store *stateDBWorkingSetStore) Stop(context.Context) error { return nil } +func (store *stateDBWorkingSetStore) GetObject(ns string, key []byte, obj any) error { + v, err := store.getKV(ns, key) + if err != nil { + return err + } + return state.Deserialize(obj, v) +} + func (store *stateDBWorkingSetStore) Get(ns string, key []byte) ([]byte, error) { + return store.getKV(ns, key) +} + +func (store *stateDBWorkingSetStore) getKV(ns string, key []byte) ([]byte, error) { data, err := store.flusher.KVStoreWithBuffer().Get(ns, key) if err != nil { if errors.Cause(err) == db.ErrNotExist { @@ -138,7 +174,7 @@ func (store *stateDBWorkingSetStore) Get(ns string, key []byte) ([]byte, error) return data, nil } -func (store *stateDBWorkingSetStore) States(ns string, keys [][]byte) ([][]byte, [][]byte, error) { +func (store *stateDBWorkingSetStore) States(ns string, keys [][]byte, obj any) ([][]byte, [][]byte, error) { if store.readBuffer { // TODO: after the 180 HF, we can revert readBuffer, and always go this case return readStates(store.flusher.KVStoreWithBuffer(), ns, keys) @@ -162,3 +198,7 @@ func (store *stateDBWorkingSetStore) FinalizeTx(_ context.Context) error { } func (store *stateDBWorkingSetStore) Close() {} + +func (store *stateDBWorkingSetStore) CreateGenesisStates(ctx context.Context) error { + return nil +} diff --git a/state/factory/workingsetstore_erigon.go b/state/factory/workingsetstore_erigon.go index 9ff9c86689..733a29220f 100644 --- a/state/factory/workingsetstore_erigon.go +++ b/state/factory/workingsetstore_erigon.go @@ -31,6 +31,7 @@ import ( "github.com/iotexproject/iotex-core/v2/db/batch" "github.com/iotexproject/iotex-core/v2/pkg/log" "github.com/iotexproject/iotex-core/v2/state" + "github.com/iotexproject/iotex-core/v2/systemcontracts" ) const ( @@ -50,6 +51,8 @@ type erigonWorkingSetStore struct { db *erigonDB intraBlockState *erigonstate.IntraBlockState tx kv.Tx + sr erigonstate.StateReader + ctx context.Context } func newErigonDB(path string) *erigonDB { @@ -88,6 +91,8 @@ func (db *erigonDB) newErigonStore(ctx context.Context, height uint64) (*erigonW db: db, tx: tx, intraBlockState: intraBlockState, + sr: r, + ctx: ctx, }, nil } @@ -102,6 +107,8 @@ func (db *erigonDB) newErigonStoreDryrun(ctx context.Context, height uint64) (*e db: db, tx: tx, intraBlockState: intraBlockState, + sr: tsw, + ctx: ctx, }, nil } @@ -274,6 +281,19 @@ func (store *erigonWorkingSetStore) RevertSnapshot(sn int) error { func (store *erigonWorkingSetStore) ResetSnapshots() {} +func (store *erigonWorkingSetStore) PutObject(ns string, key []byte, obj any) (err error) { + storage := store.objectContractStorage(obj) + if storage != nil { + log.L().Debug("put object", zap.String("namespace", ns), log.Hex("key", key), zap.String("type", fmt.Sprintf("%T", obj)), zap.Any("content", obj)) + return storage.StoreToContract(ns, key, store.newContractBackend(store.ctx, store.intraBlockState, store.sr)) + } + value, err := state.Serialize(obj) + if err != nil { + return errors.Wrapf(err, "failed to serialize object for namespace %s and key %x", ns, key) + } + return store.Put(ns, key, value) +} + func (store *erigonWorkingSetStore) Put(ns string, key []byte, value []byte) (err error) { // only handling account, contract storage handled by evm adapter // others are ignored @@ -301,6 +321,21 @@ func (store *erigonWorkingSetStore) Put(ns string, key []byte, value []byte) (er return nil } +func (store *erigonWorkingSetStore) GetObject(ns string, key []byte, obj any) error { + storage := store.objectContractStorage(obj) + if storage != nil { + defer func() { + log.L().Debug("get object", zap.String("namespace", ns), log.Hex("key", key), zap.String("type", fmt.Sprintf("%T", obj))) + }() + return storage.LoadFromContract(ns, key, store.newContractBackend(store.ctx, store.intraBlockState, store.sr)) + } + value, err := store.Get(ns, key) + if err != nil { + return errors.Wrapf(err, "failed to get object for namespace %s and key %x", ns, key) + } + return state.Deserialize(obj, value) +} + func (store *erigonWorkingSetStore) Get(ns string, key []byte) ([]byte, error) { switch ns { case AccountKVNamespace: @@ -329,6 +364,15 @@ func (store *erigonWorkingSetStore) Get(ns string, key []byte) ([]byte, error) { } } +func (store *erigonWorkingSetStore) DeleteObject(ns string, key []byte, obj any) error { + storage := store.objectContractStorage(obj) + if storage != nil { + log.L().Debug("delete object", zap.String("namespace", ns), log.Hex("key", key), zap.String("type", fmt.Sprintf("%T", obj))) + return storage.DeleteFromContract(ns, key, store.newContractBackend(store.ctx, store.intraBlockState, store.sr)) + } + return nil +} + func (store *erigonWorkingSetStore) Delete(ns string, key []byte) error { return nil } @@ -341,14 +385,59 @@ func (store *erigonWorkingSetStore) Filter(string, db.Condition, []byte, []byte) return nil, nil, nil } -func (store *erigonWorkingSetStore) States(string, [][]byte) ([][]byte, [][]byte, error) { - return nil, nil, nil +func (store *erigonWorkingSetStore) States(ns string, keys [][]byte, obj any) ([][]byte, [][]byte, error) { + storage := store.objectContractStorage(obj) + if storage == nil { + return nil, nil, errors.Wrapf(ErrNotSupported, "unsupported object type %T in ns %s", obj, ns) + } + var ( + objs []any + err error + results [][]byte + backend = store.newContractBackend(store.ctx, store.intraBlockState, store.sr) + ) + if len(keys) == 0 { + keys, objs, err = storage.ListFromContract(ns, backend) + } else { + objs, err = storage.BatchFromContract(ns, keys, backend) + } + log.L().Debug("list objs from erigon working set store", + zap.String("ns", ns), + zap.Int("num", len(keys)), + zap.Int("objsize", len(objs)), + zap.String("obj", fmt.Sprintf("%T", obj)), + ) + if err != nil { + return nil, nil, errors.Wrapf(err, "failed to list objects from erigon working set store for namespace %s", ns) + } + for i, obj := range objs { + log.L().Debug("list obj from erigon working set store", + zap.String("ns", ns), + log.Hex("key", keys[i]), + zap.String("storage", fmt.Sprintf("%T", obj)), + zap.Any("content", obj), + ) + if obj == nil { + results = append(results, nil) + continue + } + res, err := state.Serialize(obj) + if err != nil { + return nil, nil, errors.Wrapf(err, "failed to serialize object for namespace %s and key %x", ns, keys[i]) + } + results = append(results, res) + } + return keys, results, nil } func (store *erigonWorkingSetStore) Digest() hash.Hash256 { return hash.ZeroHash256 } +func (store *erigonWorkingSetStore) CreateGenesisStates(ctx context.Context) error { + return systemcontracts.DeploySystemContractsIfNotExist(store.newContractBackend(ctx, store.intraBlockState, store.sr)) +} + func (store *erigonDB) Height() (uint64, error) { var height uint64 err := store.rw.View(context.Background(), func(tx kv.Tx) error { @@ -369,3 +458,26 @@ func (store *erigonDB) Height() (uint64, error) { } return height, nil } + +func (store *erigonWorkingSetStore) newContractBackend(ctx context.Context, intraBlockState *erigonstate.IntraBlockState, sr erigonstate.StateReader) *contractBacked { + blkCtx := protocol.MustGetBlockCtx(ctx) + g, ok := genesis.ExtractGenesisContext(ctx) + if !ok { + log.S().Panic("failed to extract genesis context from block context") + } + bcCtx := protocol.MustGetBlockchainCtx(ctx) + return NewContractBackend(store.intraBlockState, store.sr, blkCtx.BlockHeight, blkCtx.BlockTimeStamp, &g, bcCtx.EvmNetworkID) +} + +func (store *erigonWorkingSetStore) objectContractStorage(obj any) state.ContractStorage { + if cs, ok := obj.(state.ContractStorage); ok { + return cs + } + if cs, ok := obj.(state.ContractStorageProxy); ok { + return cs.ContractStorageProxy() + } + if cs, ok := obj.(state.ContractStorageStandard); ok { + return state.NewContractStorageStandardWrapper(cs) + } + return nil +} diff --git a/state/factory/workingsetstore_erigon_simulate.go b/state/factory/workingsetstore_erigon_simulate.go index 81f276e437..be38bd6662 100644 --- a/state/factory/workingsetstore_erigon_simulate.go +++ b/state/factory/workingsetstore_erigon_simulate.go @@ -7,6 +7,7 @@ import ( "github.com/iotexproject/iotex-core/v2/action/protocol/execution/evm" "github.com/iotexproject/iotex-core/v2/db" + "github.com/iotexproject/iotex-core/v2/state" ) // erigonWorkingSetStoreForSimulate is a working set store that uses erigon as the main store @@ -34,6 +35,21 @@ func (store *erigonWorkingSetStoreForSimulate) Stop(context.Context) error { return nil } +func (store *erigonWorkingSetStoreForSimulate) GetObject(ns string, key []byte, obj any) error { + if _, ok := obj.(state.ContractStorage); ok { + return store.erigonStore.GetObject(ns, key, obj) + } + if _, ok := obj.(*state.Account); !ok && ns == AccountKVNamespace { + return store.store.GetObject(ns, key, obj) + } + switch ns { + case AccountKVNamespace, evm.CodeKVNameSpace: + return store.erigonStore.GetObject(ns, key, obj) + default: + return store.store.GetObject(ns, key, obj) + } +} + func (store *erigonWorkingSetStoreForSimulate) Get(ns string, key []byte) ([]byte, error) { switch ns { case AccountKVNamespace, evm.CodeKVNameSpace: @@ -43,9 +59,12 @@ func (store *erigonWorkingSetStoreForSimulate) Get(ns string, key []byte) ([]byt } } -func (store *erigonWorkingSetStoreForSimulate) States(ns string, keys [][]byte) ([][]byte, [][]byte, error) { +func (store *erigonWorkingSetStoreForSimulate) States(ns string, keys [][]byte, obj any) ([][]byte, [][]byte, error) { + if _, ok := obj.(state.ContractStorage); ok { + return store.erigonStore.States(ns, keys, obj) + } // currently only used for staking & poll, no need to read from erigon - return store.store.States(ns, keys) + return store.store.States(ns, keys, obj) } func (store *erigonWorkingSetStoreForSimulate) Finalize(_ context.Context) error { @@ -72,3 +91,7 @@ func (store *erigonWorkingSetStoreForSimulate) Commit(context.Context, uint64) e func (store *erigonWorkingSetStoreForSimulate) Close() { store.erigonStore.Close() } + +func (store *erigonWorkingSetStoreForSimulate) CreateGenesisStates(ctx context.Context) error { + return nil +} diff --git a/state/factory/workingsetstore_test.go b/state/factory/workingsetstore_test.go index dab2f99d5c..347dcbb2e6 100644 --- a/state/factory/workingsetstore_test.go +++ b/state/factory/workingsetstore_test.go @@ -53,7 +53,7 @@ func TestStateDBWorkingSetStore(t *testing.T) { valueInStore, err = store.Get(namespace, key3) require.NoError(err) require.True(bytes.Equal(value3, valueInStore)) - _, valuesInStore, err := store.States(namespace, [][]byte{key1, key2, key3}) + _, valuesInStore, err := store.States(namespace, [][]byte{key1, key2, key3}, nil) require.Equal(3, len(valuesInStore)) require.True(bytes.Equal(value1, valuesInStore[0])) require.True(bytes.Equal(value2, valuesInStore[1])) @@ -66,7 +66,7 @@ func TestStateDBWorkingSetStore(t *testing.T) { require.NoError(store.Delete(namespace, key1)) _, err = store.Get(namespace, key1) require.Error(err) - _, valuesInStore, err = store.States(namespace, [][]byte{key1, key2, key3}) + _, valuesInStore, err = store.States(namespace, [][]byte{key1, key2, key3}, nil) require.Equal(3, len(valuesInStore)) require.Nil(valuesInStore[0]) require.True(bytes.Equal(value2, valuesInStore[1])) diff --git a/state/factory/workingsetstore_with_secondary.go b/state/factory/workingsetstore_with_secondary.go index c4c28130d4..94db5ee389 100644 --- a/state/factory/workingsetstore_with_secondary.go +++ b/state/factory/workingsetstore_with_secondary.go @@ -24,18 +24,22 @@ var ( type reader interface { Get(string, []byte) ([]byte, error) - States(string, [][]byte) ([][]byte, [][]byte, error) + GetObject(string, []byte, any) error + States(string, [][]byte, any) ([][]byte, [][]byte, error) Digest() hash.Hash256 Filter(string, db.Condition, []byte, []byte) ([][]byte, [][]byte, error) } type writer interface { Put(ns string, key []byte, value []byte) error + PutObject(ns string, key []byte, obj any) error Delete(ns string, key []byte) error + DeleteObject(ns string, key []byte, obj any) error Snapshot() int RevertSnapshot(snapshot int) error ResetSnapshots() WriteBatch(batch.KVStoreBatch) error + CreateGenesisStates(context.Context) error } // treat erigon as 3rd output, still read from statedb @@ -92,6 +96,13 @@ func (store *workingSetStoreWithSecondary) Put(ns string, key []byte, value []by return store.writerSecondary.Put(ns, key, value) } +func (store *workingSetStoreWithSecondary) PutObject(ns string, key []byte, obj any) error { + if err := store.writer.PutObject(ns, key, obj); err != nil { + return err + } + return store.writerSecondary.PutObject(ns, key, obj) +} + func (store *workingSetStoreWithSecondary) Delete(ns string, key []byte) error { if err := store.writer.Delete(ns, key); err != nil { return err @@ -99,6 +110,13 @@ func (store *workingSetStoreWithSecondary) Delete(ns string, key []byte) error { return store.writerSecondary.Delete(ns, key) } +func (store *workingSetStoreWithSecondary) DeleteObject(ns string, key []byte, obj any) error { + if err := store.writer.DeleteObject(ns, key, obj); err != nil { + return err + } + return store.writerSecondary.DeleteObject(ns, key, obj) +} + func (store *workingSetStoreWithSecondary) Commit(ctx context.Context, retention uint64) error { // Commit to secondary store first, then commit to main store // This ensures that if the secondary store fails, the main store is not committed @@ -146,3 +164,18 @@ func (store *workingSetStoreWithSecondary) Close() { store.writer.Close() store.writerSecondary.Close() } + +func (store *workingSetStoreWithSecondary) CreateGenesisStates(ctx context.Context) error { + if err := store.writer.CreateGenesisStates(ctx); err != nil { + return err + } + return store.writerSecondary.CreateGenesisStates(ctx) +} + +func (store *workingSetStoreWithSecondary) GetObject(ns string, key []byte, obj any) error { + return store.reader.GetObject(ns, key, obj) +} + +func (store *workingSetStoreWithSecondary) States(ns string, keys [][]byte, obj any) ([][]byte, [][]byte, error) { + return store.reader.States(ns, keys, obj) +} From 4764e23ba0ee7d10728bcdcba0a9d0e8c380c1d2 Mon Sep 17 00:00:00 2001 From: envestcc Date: Thu, 21 Aug 2025 10:33:57 +0800 Subject: [PATCH 06/26] workingsetstore as kvstore --- state/factory/workingset.go | 6 +++- state/factory/workingsetstore.go | 8 ++++- state/factory/workingsetstore_erigon.go | 4 +++ .../workingsetstore_erigon_simulate.go | 17 +++------- state/factory/workingsetstore_test.go | 34 +++++++++++-------- .../factory/workingsetstore_with_secondary.go | 33 ++++-------------- 6 files changed, 45 insertions(+), 57 deletions(-) diff --git a/state/factory/workingset.go b/state/factory/workingset.go index 30ca383d5c..e5ed0c8296 100644 --- a/state/factory/workingset.go +++ b/state/factory/workingset.go @@ -1003,7 +1003,11 @@ func (ws *workingSet) NewWorkingSet(ctx context.Context) (*workingSet, error) { if !ws.finalized { return nil, errors.New("workingset has not been finalized yet") } - store, err := ws.workingSetStoreFactory.CreateWorkingSetStore(ctx, ws.height+1, ws.store) + kvStore := ws.store.KVStore() + if kvStore == nil { + return nil, errors.Errorf("KVStore() not supported in %T", ws.store) + } + store, err := ws.workingSetStoreFactory.CreateWorkingSetStore(ctx, ws.height+1, kvStore) if err != nil { return nil, err } diff --git a/state/factory/workingsetstore.go b/state/factory/workingsetstore.go index 57b546ee5c..ce136f9212 100644 --- a/state/factory/workingsetstore.go +++ b/state/factory/workingsetstore.go @@ -21,7 +21,9 @@ import ( type ( workingSetStore interface { - db.KVStore + Start(context.Context) error + Stop(context.Context) error + KVStore() db.KVStore PutObject(ns string, key []byte, object any) (err error) GetObject(ns string, key []byte, object any) error DeleteObject(ns string, key []byte, object any) error @@ -202,3 +204,7 @@ func (store *stateDBWorkingSetStore) Close() {} func (store *stateDBWorkingSetStore) CreateGenesisStates(ctx context.Context) error { return nil } + +func (store *stateDBWorkingSetStore) KVStore() db.KVStore { + return store +} diff --git a/state/factory/workingsetstore_erigon.go b/state/factory/workingsetstore_erigon.go index 733a29220f..2c6b4af7c1 100644 --- a/state/factory/workingsetstore_erigon.go +++ b/state/factory/workingsetstore_erigon.go @@ -481,3 +481,7 @@ func (store *erigonWorkingSetStore) objectContractStorage(obj any) state.Contrac } return nil } + +func (store *erigonWorkingSetStore) KVStore() db.KVStore { + return nil +} diff --git a/state/factory/workingsetstore_erigon_simulate.go b/state/factory/workingsetstore_erigon_simulate.go index be38bd6662..63b43da451 100644 --- a/state/factory/workingsetstore_erigon_simulate.go +++ b/state/factory/workingsetstore_erigon_simulate.go @@ -50,15 +50,6 @@ func (store *erigonWorkingSetStoreForSimulate) GetObject(ns string, key []byte, } } -func (store *erigonWorkingSetStoreForSimulate) Get(ns string, key []byte) ([]byte, error) { - switch ns { - case AccountKVNamespace, evm.CodeKVNameSpace: - return store.erigonStore.Get(ns, key) - default: - return store.store.Get(ns, key) - } -} - func (store *erigonWorkingSetStoreForSimulate) States(ns string, keys [][]byte, obj any) ([][]byte, [][]byte, error) { if _, ok := obj.(state.ContractStorage); ok { return store.erigonStore.States(ns, keys, obj) @@ -75,10 +66,6 @@ func (store *erigonWorkingSetStoreForSimulate) FinalizeTx(ctx context.Context) e return nil } -func (store *erigonWorkingSetStoreForSimulate) Filter(ns string, cond db.Condition, start, limit []byte) ([][]byte, [][]byte, error) { - return store.store.Filter(ns, cond, start, limit) -} - func (store *erigonWorkingSetStoreForSimulate) Digest() hash.Hash256 { return store.store.Digest() } @@ -95,3 +82,7 @@ func (store *erigonWorkingSetStoreForSimulate) Close() { func (store *erigonWorkingSetStoreForSimulate) CreateGenesisStates(ctx context.Context) error { return nil } + +func (store *erigonWorkingSetStoreForSimulate) KVStore() db.KVStore { + return nil +} diff --git a/state/factory/workingsetstore_test.go b/state/factory/workingsetstore_test.go index 347dcbb2e6..c10ec3de4f 100644 --- a/state/factory/workingsetstore_test.go +++ b/state/factory/workingsetstore_test.go @@ -36,21 +36,23 @@ func TestStateDBWorkingSetStore(t *testing.T) { key3 := []byte("key3") value3 := []byte("value3") t.Run("test kvstore feature", func(t *testing.T) { - _, err := store.Get(namespace, key1) + var value []byte + err := store.GetObject(namespace, key1, &value) require.Error(err) - require.NoError(store.Delete(namespace, key1)) - require.NoError(store.Put(namespace, key1, value1)) - valueInStore, err := store.Get(namespace, key1) + require.NoError(store.DeleteObject(namespace, key1, &value)) + require.NoError(store.PutObject(namespace, key1, value1)) + var valueInStore []byte + err = store.GetObject(namespace, key1, &valueInStore) require.NoError(err) require.True(bytes.Equal(value1, valueInStore)) sn1 := store.Snapshot() - require.NoError(store.Put(namespace, key2, value2)) - valueInStore, err = store.Get(namespace, key2) + require.NoError(store.PutObject(namespace, key2, value2)) + err = store.GetObject(namespace, key2, &valueInStore) require.NoError(err) require.True(bytes.Equal(value2, valueInStore)) store.Snapshot() - require.NoError(store.Put(namespace, key3, value3)) - valueInStore, err = store.Get(namespace, key3) + require.NoError(store.PutObject(namespace, key3, value3)) + err = store.GetObject(namespace, key3, &valueInStore) require.NoError(err) require.True(bytes.Equal(value3, valueInStore)) _, valuesInStore, err := store.States(namespace, [][]byte{key1, key2, key3}, nil) @@ -63,26 +65,27 @@ func TestStateDBWorkingSetStore(t *testing.T) { require.Equal("e1f83be0a44ae601061724990036b8a40edbf81cffc639657c9bb2c5d384defa", hex.EncodeToString(h[:])) }) sn3 := store.Snapshot() - require.NoError(store.Delete(namespace, key1)) - _, err = store.Get(namespace, key1) + require.NoError(store.DeleteObject(namespace, key1, &valueInStore)) + err = store.GetObject(namespace, key1, &valueInStore) require.Error(err) - _, valuesInStore, err = store.States(namespace, [][]byte{key1, key2, key3}, nil) + _, valuesInStore, err = store.States(namespace, [][]byte{key1, key2, key3}, &valueInStore) require.Equal(3, len(valuesInStore)) require.Nil(valuesInStore[0]) require.True(bytes.Equal(value2, valuesInStore[1])) require.True(bytes.Equal(value3, valuesInStore[2])) require.NoError(store.RevertSnapshot(sn3)) - valueInStore, err = store.Get(namespace, key1) + err = store.GetObject(namespace, key1, &valueInStore) require.NoError(err) require.NoError(store.RevertSnapshot(sn1)) require.True(bytes.Equal(value1, valueInStore)) - _, err = store.Get(namespace, key2) + err = store.GetObject(namespace, key2, &valueInStore) require.Error(err) }) t.Run("finalize & commit", func(t *testing.T) { height := uint64(100) ctx := context.Background() - _, err := store.Get(AccountKVNamespace, []byte(CurrentHeightKey)) + var value []byte + err := store.GetObject(AccountKVNamespace, []byte(CurrentHeightKey), &value) require.Error(err) _, err = inMemStore.Get(AccountKVNamespace, []byte(CurrentHeightKey)) require.Error(err) @@ -90,7 +93,8 @@ func TestStateDBWorkingSetStore(t *testing.T) { BlockHeight: height, }) require.NoError(store.Finalize(ctx)) - heightInStore, err := store.Get(AccountKVNamespace, []byte(CurrentHeightKey)) + var heightInStore []byte + err = store.GetObject(AccountKVNamespace, []byte(CurrentHeightKey), &heightInStore) require.NoError(err) require.True(bytes.Equal(heightInStore, byteutil.Uint64ToBytes(height))) _, err = inMemStore.Get(AccountKVNamespace, []byte(CurrentHeightKey)) diff --git a/state/factory/workingsetstore_with_secondary.go b/state/factory/workingsetstore_with_secondary.go index 94db5ee389..d053271d0d 100644 --- a/state/factory/workingsetstore_with_secondary.go +++ b/state/factory/workingsetstore_with_secondary.go @@ -8,7 +8,6 @@ import ( "github.com/prometheus/client_golang/prometheus" "github.com/iotexproject/iotex-core/v2/db" - "github.com/iotexproject/iotex-core/v2/db/batch" "github.com/iotexproject/iotex-core/v2/pkg/log" ) @@ -23,22 +22,19 @@ var ( ) type reader interface { - Get(string, []byte) ([]byte, error) + // Get(string, []byte) ([]byte, error) GetObject(string, []byte, any) error States(string, [][]byte, any) ([][]byte, [][]byte, error) Digest() hash.Hash256 - Filter(string, db.Condition, []byte, []byte) ([][]byte, [][]byte, error) + // Filter(string, db.Condition, []byte, []byte) ([][]byte, [][]byte, error) } type writer interface { - Put(ns string, key []byte, value []byte) error PutObject(ns string, key []byte, obj any) error - Delete(ns string, key []byte) error DeleteObject(ns string, key []byte, obj any) error Snapshot() int RevertSnapshot(snapshot int) error ResetSnapshots() - WriteBatch(batch.KVStoreBatch) error CreateGenesisStates(context.Context) error } @@ -82,20 +78,6 @@ func (store *workingSetStoreWithSecondary) FinalizeTx(ctx context.Context) error return store.writerSecondary.FinalizeTx(ctx) } -func (store *workingSetStoreWithSecondary) WriteBatch(batch batch.KVStoreBatch) error { - if err := store.writer.WriteBatch(batch); err != nil { - return err - } - return store.writerSecondary.WriteBatch(batch) -} - -func (store *workingSetStoreWithSecondary) Put(ns string, key []byte, value []byte) error { - if err := store.writer.Put(ns, key, value); err != nil { - return err - } - return store.writerSecondary.Put(ns, key, value) -} - func (store *workingSetStoreWithSecondary) PutObject(ns string, key []byte, obj any) error { if err := store.writer.PutObject(ns, key, obj); err != nil { return err @@ -103,13 +85,6 @@ func (store *workingSetStoreWithSecondary) PutObject(ns string, key []byte, obj return store.writerSecondary.PutObject(ns, key, obj) } -func (store *workingSetStoreWithSecondary) Delete(ns string, key []byte) error { - if err := store.writer.Delete(ns, key); err != nil { - return err - } - return store.writerSecondary.Delete(ns, key) -} - func (store *workingSetStoreWithSecondary) DeleteObject(ns string, key []byte, obj any) error { if err := store.writer.DeleteObject(ns, key, obj); err != nil { return err @@ -179,3 +154,7 @@ func (store *workingSetStoreWithSecondary) GetObject(ns string, key []byte, obj func (store *workingSetStoreWithSecondary) States(ns string, keys [][]byte, obj any) ([][]byte, [][]byte, error) { return store.reader.States(ns, keys, obj) } + +func (store *workingSetStoreWithSecondary) KVStore() db.KVStore { + return nil +} From cec240f27cfda081ed3e2cf6db9fc3cd29c6e74c Mon Sep 17 00:00:00 2001 From: envestcc Date: Fri, 22 Aug 2025 18:07:35 +0800 Subject: [PATCH 07/26] systemcontract efficiency --- systemcontracts/GenericStorage.sol | 91 ++++++++++------- systemcontracts/NamespaceStorage.sol | 119 +++++++++++++---------- systemcontracts/generic_storage_abi.go | 2 +- systemcontracts/namespace_storage_abi.go | 2 +- 4 files changed, 126 insertions(+), 88 deletions(-) diff --git a/systemcontracts/GenericStorage.sol b/systemcontracts/GenericStorage.sol index 33e586c3e2..e40f7b3090 100644 --- a/systemcontracts/GenericStorage.sol +++ b/systemcontracts/GenericStorage.sol @@ -24,14 +24,15 @@ contract GenericStorage { bytes auxiliaryData; // Additional data field for flexibility } - // Main storage mapping - mapping(bytes => GenericValue) private storage_; - // Array to keep track of all keys for listing functionality bytes[] private keys_; - // Mapping to check if a key exists (for efficient existence checks) - mapping(bytes => bool) private keyExists_; + // Array to store values corresponding to keys (parallel arrays) + GenericValue[] private values_; + + // Mapping to store the index of each key in the keys_ array for O(1) removal + // Note: We store (actualIndex + 1) to distinguish between non-existent keys (0) and keys at index 0 (1) + mapping(bytes => uint256) private keyIndex_; // Events event DataStored(bytes indexed key); @@ -39,6 +40,15 @@ contract GenericStorage { event BatchDataRetrieved(uint256 keyCount); event StorageCleared(); + /** + * @dev Internal function to check if a key exists + * @param key The storage key to check + * @return Whether the key exists + */ + function _keyExists(bytes memory key) private view returns (bool) { + return keyIndex_[key] != 0; + } + /** * @dev Store data with a given key * @param key The storage key @@ -51,14 +61,16 @@ contract GenericStorage { require(key.length > 0, "Key cannot be empty"); // If key doesn't exist, add it to keys array - if (!keyExists_[key]) { + if (!_keyExists(key)) { + keyIndex_[key] = keys_.length + 1; // Store (index + 1) to distinguish from non-existent keys keys_.push(key); - keyExists_[key] = true; + values_.push(value); // Add corresponding value to values array + } else { + // Update existing value + uint256 index = keyIndex_[key] - 1; + values_[index] = value; } - // Store the value - storage_[key] = value; - emit DataStored(key); } @@ -67,22 +79,27 @@ contract GenericStorage { * @param key The storage key to delete */ function remove(bytes memory key) external { - require(keyExists_[key], "Key does not exist"); - - // Remove from storage - delete storage_[key]; - keyExists_[key] = false; - - // Remove from keys array - for (uint256 i = 0; i < keys_.length; i++) { - if (keccak256(keys_[i]) == keccak256(key)) { - // Move last element to current position and pop - keys_[i] = keys_[keys_.length - 1]; - keys_.pop(); - break; - } + require(_keyExists(key), "Key does not exist"); + + // Get the index of the key to remove (subtract 1 since we stored index + 1) + uint256 indexToRemove = keyIndex_[key] - 1; + uint256 lastIndex = keys_.length - 1; + + // If it's not the last element, move the last element to the removed position + if (indexToRemove != lastIndex) { + bytes memory lastKey = keys_[lastIndex]; + GenericValue memory lastValue = values_[lastIndex]; + + keys_[indexToRemove] = lastKey; + values_[indexToRemove] = lastValue; // Move the corresponding value + keyIndex_[lastKey] = indexToRemove + 1; // Update the moved key's index (add 1) } + // Remove the last elements from both arrays + keys_.pop(); + values_.pop(); + delete keyIndex_[key]; + emit DataDeleted(key); } @@ -93,9 +110,10 @@ contract GenericStorage { * @return keyExists Whether the key exists */ function get(bytes memory key) external view returns (GenericValue memory value, bool keyExists) { - keyExists = keyExists_[key]; + keyExists = _keyExists(key); if (keyExists) { - value = storage_[key]; + uint256 index = keyIndex_[key] - 1; + value = values_[index]; // Get value from values array } return (value, keyExists); } @@ -114,9 +132,10 @@ contract GenericStorage { existsFlags = new bool[](keyList.length); for (uint256 i = 0; i < keyList.length; i++) { - existsFlags[i] = keyExists_[keyList[i]]; + existsFlags[i] = _keyExists(keyList[i]); if (existsFlags[i]) { - values[i] = storage_[keyList[i]]; + uint256 index = keyIndex_[keyList[i]] - 1; + values[i] = values_[index]; // Get value from values array } } @@ -153,11 +172,11 @@ contract GenericStorage { keyList = new bytes[](actualLimit); values = new GenericValue[](actualLimit); - // Fill result arrays + // Fill result arrays - much more efficient with parallel arrays for (uint256 i = 0; i < actualLimit; i++) { - bytes memory key = keys_[offset + i]; - keyList[i] = key; - values[i] = storage_[key]; + uint256 arrayIndex = offset + i; + keyList[i] = keys_[arrayIndex]; + values[i] = values_[arrayIndex]; // Direct array access, no mapping lookup needed } return (keyList, values, total); @@ -199,7 +218,7 @@ contract GenericStorage { * @return keyExists Whether the key exists */ function exists(bytes memory key) external view returns (bool keyExists) { - return keyExists_[key]; + return _keyExists(key); } /** @@ -218,12 +237,12 @@ contract GenericStorage { // Clear all mappings and arrays for (uint256 i = 0; i < keys_.length; i++) { bytes memory key = keys_[i]; - delete storage_[key]; - keyExists_[key] = false; + delete keyIndex_[key]; } - // Clear keys array + // Clear both arrays delete keys_; + delete values_; emit StorageCleared(); } diff --git a/systemcontracts/NamespaceStorage.sol b/systemcontracts/NamespaceStorage.sol index 1ae024cf80..f5590b3383 100644 --- a/systemcontracts/NamespaceStorage.sol +++ b/systemcontracts/NamespaceStorage.sol @@ -20,14 +20,13 @@ contract NamespaceStorage { bytes auxiliaryData; // Additional data field for flexibility } - // Nested mapping: namespace => key => value - mapping(string => mapping(bytes => GenericValue)) private namespaceStorage_; - - // Track keys for each namespace + // Track keys for each namespace (parallel arrays) mapping(string => bytes[]) private namespaceKeys_; + mapping(string => GenericValue[]) private namespaceValues_; - // Track if a key exists in a namespace - mapping(string => mapping(bytes => bool)) private keyExists_; + // Mapping to store the index of each key in the namespace's keys array for O(1) removal + // Note: We store (actualIndex + 1) to distinguish between non-existent keys (0) and keys at index 0 (1) + mapping(string => mapping(bytes => uint256)) private keyIndex_; // Track all namespaces string[] private namespaces_; @@ -40,6 +39,16 @@ contract NamespaceStorage { event NamespaceCleared(string indexed namespace); event AllDataCleared(); + /** + * @dev Internal function to check if a key exists in a namespace + * @param namespace The namespace to check + * @param key The storage key to check + * @return Whether the key exists in the namespace + */ + function _keyExists(string memory namespace, bytes memory key) private view returns (bool) { + return keyIndex_[namespace][key] != 0; + } + /** * @dev Store data with a given namespace and key * @param namespace The namespace for data isolation @@ -60,15 +69,17 @@ contract NamespaceStorage { namespaceExists_[namespace] = true; } - // If key doesn't exist in this namespace, add it to keys array - if (!keyExists_[namespace][key]) { + // If key doesn't exist in this namespace, add it to both arrays + if (!_keyExists(namespace, key)) { + keyIndex_[namespace][key] = namespaceKeys_[namespace].length + 1; // Store (index + 1) namespaceKeys_[namespace].push(key); - keyExists_[namespace][key] = true; + namespaceValues_[namespace].push(value); + } else { + // Update existing value + uint256 index = keyIndex_[namespace][key] - 1; + namespaceValues_[namespace][index] = value; } - // Store the value - namespaceStorage_[namespace][key] = value; - emit DataStored(namespace, key); } @@ -83,9 +94,10 @@ contract NamespaceStorage { GenericValue memory value, bool keyExists ) { - keyExists = keyExists_[namespace][key]; + keyExists = _keyExists(namespace, key); if (keyExists) { - value = namespaceStorage_[namespace][key]; + uint256 index = keyIndex_[namespace][key] - 1; + value = namespaceValues_[namespace][index]; } return (value, keyExists); } @@ -97,23 +109,27 @@ contract NamespaceStorage { */ function remove(string memory namespace, bytes memory key) external { require(namespaceExists_[namespace], "Namespace does not exist"); - require(keyExists_[namespace][key], "Key does not exist in namespace"); - - // Remove from storage - delete namespaceStorage_[namespace][key]; - keyExists_[namespace][key] = false; - - // Remove from keys array - bytes[] storage keys = namespaceKeys_[namespace]; - for (uint256 i = 0; i < keys.length; i++) { - if (keccak256(keys[i]) == keccak256(key)) { - // Move last element to current position and pop - keys[i] = keys[keys.length - 1]; - keys.pop(); - break; - } + require(_keyExists(namespace, key), "Key does not exist in namespace"); + + // Get the index of the key to remove (subtract 1 since we stored index + 1) + uint256 indexToRemove = keyIndex_[namespace][key] - 1; + uint256 lastIndex = namespaceKeys_[namespace].length - 1; + + // If it's not the last element, move the last element to the removed position + if (indexToRemove != lastIndex) { + bytes memory lastKey = namespaceKeys_[namespace][lastIndex]; + GenericValue memory lastValue = namespaceValues_[namespace][lastIndex]; + + namespaceKeys_[namespace][indexToRemove] = lastKey; + namespaceValues_[namespace][indexToRemove] = lastValue; + keyIndex_[namespace][lastKey] = indexToRemove + 1; // Update the moved key's index (add 1) } + // Remove the last elements from both arrays + namespaceKeys_[namespace].pop(); + namespaceValues_[namespace].pop(); + delete keyIndex_[namespace][key]; + emit DataDeleted(namespace, key); } @@ -132,9 +148,10 @@ contract NamespaceStorage { existsFlags = new bool[](keyList.length); for (uint256 i = 0; i < keyList.length; i++) { - existsFlags[i] = keyExists_[namespace][keyList[i]]; + existsFlags[i] = _keyExists(namespace, keyList[i]); if (existsFlags[i]) { - values[i] = namespaceStorage_[namespace][keyList[i]]; + uint256 index = keyIndex_[namespace][keyList[i]] - 1; + values[i] = namespaceValues_[namespace][index]; } } @@ -164,15 +181,17 @@ contract NamespaceStorage { for (uint256 i = 0; i < keys.length; i++) { require(keys[i].length > 0, "Key cannot be empty"); - // If key doesn't exist in this namespace, add it to keys array - if (!keyExists_[namespace][keys[i]]) { + // If key doesn't exist in this namespace, add it to both arrays + if (!_keyExists(namespace, keys[i])) { + keyIndex_[namespace][keys[i]] = namespaceKeys_[namespace].length + 1; namespaceKeys_[namespace].push(keys[i]); - keyExists_[namespace][keys[i]] = true; + namespaceValues_[namespace].push(values[i]); + } else { + // Update existing value + uint256 index = keyIndex_[namespace][keys[i]] - 1; + namespaceValues_[namespace][index] = values[i]; } - // Store the value - namespaceStorage_[namespace][keys[i]] = values[i]; - emit DataStored(namespace, keys[i]); } } @@ -209,11 +228,11 @@ contract NamespaceStorage { keyList = new bytes[](actualLimit); values = new GenericValue[](actualLimit); - // Fill result arrays + // Fill result arrays - much more efficient with parallel arrays for (uint256 i = 0; i < actualLimit; i++) { - bytes memory key = keys[offset + i]; - keyList[i] = key; - values[i] = namespaceStorage_[namespace][key]; + uint256 arrayIndex = offset + i; + keyList[i] = keys[arrayIndex]; + values[i] = namespaceValues_[namespace][arrayIndex]; // Direct array access, no mapping lookup } return (keyList, values, total); @@ -294,7 +313,7 @@ contract NamespaceStorage { * @return keyExists Whether the key exists in the namespace */ function exists(string memory namespace, bytes memory key) external view returns (bool keyExists) { - return keyExists_[namespace][key]; + return _keyExists(namespace, key); } /** @@ -343,15 +362,15 @@ contract NamespaceStorage { bytes[] storage keys = namespaceKeys_[namespace]; - // Clear all data in the namespace + // Clear all key indices in the namespace for (uint256 i = 0; i < keys.length; i++) { bytes memory key = keys[i]; - delete namespaceStorage_[namespace][key]; - keyExists_[namespace][key] = false; + delete keyIndex_[namespace][key]; } - // Clear keys array for the namespace + // Clear both arrays for the namespace delete namespaceKeys_[namespace]; + delete namespaceValues_[namespace]; emit NamespaceCleared(namespace); } @@ -366,15 +385,15 @@ contract NamespaceStorage { string memory namespace = namespaces_[i]; bytes[] storage keys = namespaceKeys_[namespace]; - // Clear all data in this namespace + // Clear all key indices in this namespace for (uint256 j = 0; j < keys.length; j++) { bytes memory key = keys[j]; - delete namespaceStorage_[namespace][key]; - keyExists_[namespace][key] = false; + delete keyIndex_[namespace][key]; } - // Clear keys array for this namespace + // Clear both arrays for this namespace delete namespaceKeys_[namespace]; + delete namespaceValues_[namespace]; namespaceExists_[namespace] = false; } diff --git a/systemcontracts/generic_storage_abi.go b/systemcontracts/generic_storage_abi.go index 62d8977d3e..c61721a860 100644 --- a/systemcontracts/generic_storage_abi.go +++ b/systemcontracts/generic_storage_abi.go @@ -298,4 +298,4 @@ const GenericStorageABI = `[ } ]` -const GenericStorageByteCodeStr = "608060405234801561001057600080fd5b50612437806100206000396000f3fe608060405234801561001057600080fd5b50600436106100935760003560e01c806352efea6e1161006657806352efea6e1461013557806358edef4c1461013f57806379fc09a21461015b578063821bef2f1461018b578063d6d7d525146101bc57610093565b806306661abd14610098578063072957b0146100b657806342e1ae2e146100d257806350fd736714610103575b600080fd5b6100a06101ed565b6040516100ad9190611423565b60405180910390f35b6100d060048036038101906100cb919061165a565b6101fa565b005b6100ec60048036038101906100e791906117b8565b610385565b6040516100fa929190611a6a565b60405180910390f35b61011d60048036038101906101189190611acd565b6106ed565b60405161012c93929190611bcf565b60405180910390f35b61013d610b6d565b005b61015960048036038101906101549190611c14565b610cfb565b005b61017560048036038101906101709190611c14565b610f1e565b6040516101829190611c6c565b60405180910390f35b6101a560048036038101906101a09190611acd565b610f53565b6040516101b3929190611c87565b60405180910390f35b6101d660048036038101906101d19190611c14565b611122565b6040516101e4929190611d15565b60405180910390f35b6000600180549050905090565b600082511161023e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161023590611da2565b60405180910390fd5b60028260405161024e9190611dfe565b908152602001604051809103902060009054906101000a900460ff166102db576001829080600181540180825580915050600190039060005260206000200160009091909190915090816102a29190612021565b5060016002836040516102b59190611dfe565b908152602001604051809103902060006101000a81548160ff0219169083151502179055505b806000836040516102ec9190611dfe565b9081526020016040518091039020600082015181600001908161030f9190612021565b5060208201518160010190816103259190612021565b50604082015181600201908161033b9190612021565b509050508160405161034d9190611dfe565b60405180910390207f281be1a469724e78f8c4152bcc9fb70a95646c3e1e2ade9293d8d497c976338a60405160405180910390a25050565b606080825167ffffffffffffffff8111156103a3576103a261146d565b5b6040519080825280602002602001820160405280156103dc57816020015b6103c9611347565b8152602001906001900390816103c15790505b509150825167ffffffffffffffff8111156103fa576103f961146d565b5b6040519080825280602002602001820160405280156104285781602001602082028036833780820191505090505b50905060005b83518110156106e757600284828151811061044c5761044b6120f3565b5b60200260200101516040516104619190611dfe565b908152602001604051809103902060009054906101000a900460ff168282815181106104905761048f6120f3565b5b6020026020010190151590811515815250508181815181106104b5576104b46120f3565b5b6020026020010151156106da5760008482815181106104d7576104d66120f3565b5b60200260200101516040516104ec9190611dfe565b908152602001604051809103902060405180606001604052908160008201805461051590611e44565b80601f016020809104026020016040519081016040528092919081815260200182805461054190611e44565b801561058e5780601f106105635761010080835404028352916020019161058e565b820191906000526020600020905b81548152906001019060200180831161057157829003601f168201915b505050505081526020016001820180546105a790611e44565b80601f01602080910402602001604051908101604052809291908181526020018280546105d390611e44565b80156106205780601f106105f557610100808354040283529160200191610620565b820191906000526020600020905b81548152906001019060200180831161060357829003601f168201915b5050505050815260200160028201805461063990611e44565b80601f016020809104026020016040519081016040528092919081815260200182805461066590611e44565b80156106b25780601f10610687576101008083540402835291602001916106b2565b820191906000526020600020905b81548152906001019060200180831161069557829003601f168201915b5050505050815250508382815181106106ce576106cd6120f3565b5b60200260200101819052505b808060010191505061042e565b50915091565b606080600060018054905090508085106107ae57600067ffffffffffffffff81111561071c5761071b61146d565b5b60405190808252806020026020018201604052801561074f57816020015b606081526020019060019003908161073a5790505b509250600067ffffffffffffffff81111561076d5761076c61146d565b5b6040519080825280602002602001820160405280156107a657816020015b610793611347565b81526020019060019003908161078b5790505b509150610b66565b600085826107bc9190612151565b905060008186116107cd57856107cf565b815b90508067ffffffffffffffff8111156107eb576107ea61146d565b5b60405190808252806020026020018201604052801561081e57816020015b60608152602001906001900390816108095790505b5094508067ffffffffffffffff81111561083b5761083a61146d565b5b60405190808252806020026020018201604052801561087457816020015b610861611347565b8152602001906001900390816108595790505b50935060005b81811015610b625760006001828a6108929190612185565b815481106108a3576108a26120f3565b5b9060005260206000200180546108b890611e44565b80601f01602080910402602001604051908101604052809291908181526020018280546108e490611e44565b80156109315780601f1061090657610100808354040283529160200191610931565b820191906000526020600020905b81548152906001019060200180831161091457829003601f168201915b505050505090508087838151811061094c5761094b6120f3565b5b60200260200101819052506000816040516109679190611dfe565b908152602001604051809103902060405180606001604052908160008201805461099090611e44565b80601f01602080910402602001604051908101604052809291908181526020018280546109bc90611e44565b8015610a095780601f106109de57610100808354040283529160200191610a09565b820191906000526020600020905b8154815290600101906020018083116109ec57829003601f168201915b50505050508152602001600182018054610a2290611e44565b80601f0160208091040260200160405190810160405280929190818152602001828054610a4e90611e44565b8015610a9b5780601f10610a7057610100808354040283529160200191610a9b565b820191906000526020600020905b815481529060010190602001808311610a7e57829003601f168201915b50505050508152602001600282018054610ab490611e44565b80601f0160208091040260200160405190810160405280929190818152602001828054610ae090611e44565b8015610b2d5780601f10610b0257610100808354040283529160200191610b2d565b820191906000526020600020905b815481529060010190602001808311610b1057829003601f168201915b505050505081525050868381518110610b4957610b486120f3565b5b602002602001018190525050808060010191505061087a565b5050505b9250925092565b60005b600180549050811015610cbe57600060018281548110610b9357610b926120f3565b5b906000526020600020018054610ba890611e44565b80601f0160208091040260200160405190810160405280929190818152602001828054610bd490611e44565b8015610c215780601f10610bf657610100808354040283529160200191610c21565b820191906000526020600020905b815481529060010190602001808311610c0457829003601f168201915b50505050509050600081604051610c389190611dfe565b908152602001604051809103902060008082016000610c579190611368565b600182016000610c679190611368565b600282016000610c779190611368565b50506000600282604051610c8b9190611dfe565b908152602001604051809103902060006101000a81548160ff021916908315150217905550508080600101915050610b70565b5060016000610ccd91906113a8565b7f6c7e419df39ff46e811e7d979ebfd916b8d4960de06f479dc69cf8417cdb89e760405160405180910390a1565b600281604051610d0b9190611dfe565b908152602001604051809103902060009054906101000a900460ff16610d66576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610d5d90612205565b60405180910390fd5b600081604051610d769190611dfe565b908152602001604051809103902060008082016000610d959190611368565b600182016000610da59190611368565b600282016000610db59190611368565b50506000600282604051610dc99190611dfe565b908152602001604051809103902060006101000a81548160ff02191690831515021790555060005b600180549050811015610ed857818051906020012060018281548110610e1a57610e196120f3565b5b90600052602060002001604051610e3191906122a8565b604051809103902003610ecb576001808080549050610e509190612151565b81548110610e6157610e606120f3565b5b9060005260206000200160018281548110610e7f57610e7e6120f3565b5b906000526020600020019081610e9591906122ea565b506001805480610ea857610ea76123d2565b5b600190038181906000526020600020016000610ec49190611368565b9055610ed8565b8080600101915050610df1565b5080604051610ee79190611dfe565b60405180910390207f9248955bf73fd007be0a0d9dc13c36f9e61c3642fbac04d8ac592e0c21d0103760405160405180910390a250565b6000600282604051610f309190611dfe565b908152602001604051809103902060009054906101000a900460ff169050919050565b606060006001805490509050808410610fbc57600067ffffffffffffffff811115610f8157610f8061146d565b5b604051908082528060200260200182016040528015610fb457816020015b6060815260200190600190039081610f9f5790505b50915061111b565b60008482610fca9190612151565b90506000818511610fdb5784610fdd565b815b90508067ffffffffffffffff811115610ff957610ff861146d565b5b60405190808252806020026020018201604052801561102c57816020015b60608152602001906001900390816110175790505b50935060005b8181101561111757600181886110489190612185565b81548110611059576110586120f3565b5b90600052602060002001805461106e90611e44565b80601f016020809104026020016040519081016040528092919081815260200182805461109a90611e44565b80156110e75780601f106110bc576101008083540402835291602001916110e7565b820191906000526020600020905b8154815290600101906020018083116110ca57829003601f168201915b50505050508582815181106110ff576110fe6120f3565b5b60200260200101819052508080600101915050611032565b5050505b9250929050565b61112a611347565b600060028360405161113c9190611dfe565b908152602001604051809103902060009054906101000a900460ff1690508015611342576000836040516111709190611dfe565b908152602001604051809103902060405180606001604052908160008201805461119990611e44565b80601f01602080910402602001604051908101604052809291908181526020018280546111c590611e44565b80156112125780601f106111e757610100808354040283529160200191611212565b820191906000526020600020905b8154815290600101906020018083116111f557829003601f168201915b5050505050815260200160018201805461122b90611e44565b80601f016020809104026020016040519081016040528092919081815260200182805461125790611e44565b80156112a45780601f10611279576101008083540402835291602001916112a4565b820191906000526020600020905b81548152906001019060200180831161128757829003601f168201915b505050505081526020016002820180546112bd90611e44565b80601f01602080910402602001604051908101604052809291908181526020018280546112e990611e44565b80156113365780601f1061130b57610100808354040283529160200191611336565b820191906000526020600020905b81548152906001019060200180831161131957829003601f168201915b50505050508152505091505b915091565b60405180606001604052806060815260200160608152602001606081525090565b50805461137490611e44565b6000825580601f1061138657506113a5565b601f0160209004906000526020600020908101906113a491906113c9565b5b50565b50805460008255906000526020600020908101906113c691906113e6565b50565b5b808211156113e25760008160009055506001016113ca565b5090565b5b8082111561140657600081816113fd9190611368565b506001016113e7565b5090565b6000819050919050565b61141d8161140a565b82525050565b60006020820190506114386000830184611414565b92915050565b6000604051905090565b600080fd5b600080fd5b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6114a58261145c565b810181811067ffffffffffffffff821117156114c4576114c361146d565b5b80604052505050565b60006114d761143e565b90506114e3828261149c565b919050565b600067ffffffffffffffff8211156115035761150261146d565b5b61150c8261145c565b9050602081019050919050565b82818337600083830152505050565b600061153b611536846114e8565b6114cd565b90508281526020810184848401111561155757611556611457565b5b611562848285611519565b509392505050565b600082601f83011261157f5761157e611452565b5b813561158f848260208601611528565b91505092915050565b600080fd5b600080fd5b6000606082840312156115b8576115b7611598565b5b6115c260606114cd565b9050600082013567ffffffffffffffff8111156115e2576115e161159d565b5b6115ee8482850161156a565b600083015250602082013567ffffffffffffffff8111156116125761161161159d565b5b61161e8482850161156a565b602083015250604082013567ffffffffffffffff8111156116425761164161159d565b5b61164e8482850161156a565b60408301525092915050565b6000806040838503121561167157611670611448565b5b600083013567ffffffffffffffff81111561168f5761168e61144d565b5b61169b8582860161156a565b925050602083013567ffffffffffffffff8111156116bc576116bb61144d565b5b6116c8858286016115a2565b9150509250929050565b600067ffffffffffffffff8211156116ed576116ec61146d565b5b602082029050602081019050919050565b600080fd5b6000611716611711846116d2565b6114cd565b90508083825260208201905060208402830185811115611739576117386116fe565b5b835b8181101561178057803567ffffffffffffffff81111561175e5761175d611452565b5b80860161176b898261156a565b8552602085019450505060208101905061173b565b5050509392505050565b600082601f83011261179f5761179e611452565b5b81356117af848260208601611703565b91505092915050565b6000602082840312156117ce576117cd611448565b5b600082013567ffffffffffffffff8111156117ec576117eb61144d565b5b6117f88482850161178a565b91505092915050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b600081519050919050565b600082825260208201905092915050565b60005b8381101561186757808201518184015260208101905061184c565b60008484015250505050565b600061187e8261182d565b6118888185611838565b9350611898818560208601611849565b6118a18161145c565b840191505092915050565b600060608301600083015184820360008601526118c98282611873565b915050602083015184820360208601526118e38282611873565b915050604083015184820360408601526118fd8282611873565b9150508091505092915050565b600061191683836118ac565b905092915050565b6000602082019050919050565b600061193682611801565b611940818561180c565b9350836020820285016119528561181d565b8060005b8581101561198e578484038952815161196f858261190a565b945061197a8361191e565b925060208a01995050600181019050611956565b50829750879550505050505092915050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b60008115159050919050565b6119e1816119cc565b82525050565b60006119f383836119d8565b60208301905092915050565b6000602082019050919050565b6000611a17826119a0565b611a2181856119ab565b9350611a2c836119bc565b8060005b83811015611a5d578151611a4488826119e7565b9750611a4f836119ff565b925050600181019050611a30565b5085935050505092915050565b60006040820190508181036000830152611a84818561192b565b90508181036020830152611a988184611a0c565b90509392505050565b611aaa8161140a565b8114611ab557600080fd5b50565b600081359050611ac781611aa1565b92915050565b60008060408385031215611ae457611ae3611448565b5b6000611af285828601611ab8565b9250506020611b0385828601611ab8565b9150509250929050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b6000611b458383611873565b905092915050565b6000602082019050919050565b6000611b6582611b0d565b611b6f8185611b18565b935083602082028501611b8185611b29565b8060005b85811015611bbd5784840389528151611b9e8582611b39565b9450611ba983611b4d565b925060208a01995050600181019050611b85565b50829750879550505050505092915050565b60006060820190508181036000830152611be98186611b5a565b90508181036020830152611bfd818561192b565b9050611c0c6040830184611414565b949350505050565b600060208284031215611c2a57611c29611448565b5b600082013567ffffffffffffffff811115611c4857611c4761144d565b5b611c548482850161156a565b91505092915050565b611c66816119cc565b82525050565b6000602082019050611c816000830184611c5d565b92915050565b60006040820190508181036000830152611ca18185611b5a565b9050611cb06020830184611414565b9392505050565b60006060830160008301518482036000860152611cd48282611873565b91505060208301518482036020860152611cee8282611873565b91505060408301518482036040860152611d088282611873565b9150508091505092915050565b60006040820190508181036000830152611d2f8185611cb7565b9050611d3e6020830184611c5d565b9392505050565b600082825260208201905092915050565b7f4b65792063616e6e6f7420626520656d70747900000000000000000000000000600082015250565b6000611d8c601383611d45565b9150611d9782611d56565b602082019050919050565b60006020820190508181036000830152611dbb81611d7f565b9050919050565b600081905092915050565b6000611dd88261182d565b611de28185611dc2565b9350611df2818560208601611849565b80840191505092915050565b6000611e0a8284611dcd565b915081905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b60006002820490506001821680611e5c57607f821691505b602082108103611e6f57611e6e611e15565b5b50919050565b60008190508160005260206000209050919050565b60006020601f8301049050919050565b600082821b905092915050565b600060088302611ed77fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82611e9a565b611ee18683611e9a565b95508019841693508086168417925050509392505050565b6000819050919050565b6000611f1e611f19611f148461140a565b611ef9565b61140a565b9050919050565b6000819050919050565b611f3883611f03565b611f4c611f4482611f25565b848454611ea7565b825550505050565b600090565b611f61611f54565b611f6c818484611f2f565b505050565b5b81811015611f9057611f85600082611f59565b600181019050611f72565b5050565b601f821115611fd557611fa681611e75565b611faf84611e8a565b81016020851015611fbe578190505b611fd2611fca85611e8a565b830182611f71565b50505b505050565b600082821c905092915050565b6000611ff860001984600802611fda565b1980831691505092915050565b60006120118383611fe7565b9150826002028217905092915050565b61202a8261182d565b67ffffffffffffffff8111156120435761204261146d565b5b61204d8254611e44565b612058828285611f94565b600060209050601f83116001811461208b5760008415612079578287015190505b6120838582612005565b8655506120eb565b601f19841661209986611e75565b60005b828110156120c15784890151825560018201915060208501945060208101905061209c565b868310156120de57848901516120da601f891682611fe7565b8355505b6001600288020188555050505b505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600061215c8261140a565b91506121678361140a565b925082820390508181111561217f5761217e612122565b5b92915050565b60006121908261140a565b915061219b8361140a565b92508282019050808211156121b3576121b2612122565b5b92915050565b7f4b657920646f6573206e6f742065786973740000000000000000000000000000600082015250565b60006121ef601283611d45565b91506121fa826121b9565b602082019050919050565b6000602082019050818103600083015261221e816121e2565b9050919050565b6000815461223281611e44565b61223c8186611dc2565b94506001821660008114612257576001811461226c5761229f565b60ff198316865281151582028601935061229f565b61227585611e75565b60005b8381101561229757815481890152600182019150602081019050612278565b838801955050505b50505092915050565b60006122b48284612225565b915081905092915050565b6000815490506122ce81611e44565b9050919050565b60008190508160005260206000209050919050565b8181036122f85750506123d0565b612301826122bf565b67ffffffffffffffff81111561231a5761231961146d565b5b6123248254611e44565b61232f828285611f94565b6000601f83116001811461235e576000841561234c578287015490505b6123568582612005565b8655506123c9565b601f19841661236c876122d5565b965061237786611e75565b60005b8281101561239f5784890154825560018201915060018501945060208101905061237a565b868310156123bc57848901546123b8601f891682611fe7565b8355505b6001600288020188555050505b5050505050505b565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fdfea26469706673582212204b40ecf4db330d4b4846e1801fcbe82f88d48e72aca826e80879a5f928ee75b164736f6c63430008180033" +const GenericStorageByteCodeStr = "608060405234801561001057600080fd5b50612605806100206000396000f3fe608060405234801561001057600080fd5b50600436106100935760003560e01c806352efea6e1161006657806352efea6e1461013557806358edef4c1461013f57806379fc09a21461015b578063821bef2f1461018b578063d6d7d525146101bc57610093565b806306661abd14610098578063072957b0146100b657806342e1ae2e146100d257806350fd736714610103575b600080fd5b6100a06101ed565b6040516100ad919061179e565b60405180910390f35b6100d060048036038101906100cb91906119d5565b6101f9565b005b6100ec60048036038101906100e79190611b33565b610407565b6040516100fa929190611de5565b60405180910390f35b61011d60048036038101906101189190611e48565b610780565b60405161012c93929190611f4a565b60405180910390f35b61013d610c03565b005b61015960048036038101906101549190611f8f565b610d37565b005b61017560048036038101906101709190611f8f565b611216565b6040516101829190611fe7565b60405180910390f35b6101a560048036038101906101a09190611e48565b611228565b6040516101b3929190612002565b60405180910390f35b6101d660048036038101906101d19190611f8f565b6113f6565b6040516101e4929190612090565b60405180910390f35b60008080549050905090565b600082511161023d576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016102349061211d565b60405180910390fd5b6102468261162c565b61032857600160008054905061025c919061216c565b60028360405161026c91906121dc565b9081526020016040518091039020819055506000829080600181540180825580915050600190039060005260206000200160009091909190915090816102b291906123ff565b50600181908060018154018082558091505060019003906000526020600020906003020160009091909190915060008201518160000190816102f491906123ff565b50602082015181600101908161030a91906123ff565b50604082015181600201908161032091906123ff565b5050506103c1565b6000600160028460405161033c91906121dc565b90815260200160405180910390205461035591906124d1565b9050816001828154811061036c5761036b612505565b5b9060005260206000209060030201600082015181600001908161038f91906123ff565b5060208201518160010190816103a591906123ff565b5060408201518160020190816103bb91906123ff565b50905050505b816040516103cf91906121dc565b60405180910390207f281be1a469724e78f8c4152bcc9fb70a95646c3e1e2ade9293d8d497c976338a60405160405180910390a25050565b606080825167ffffffffffffffff811115610425576104246117e8565b5b60405190808252806020026020018201604052801561045e57816020015b61044b611657565b8152602001906001900390816104435790505b509150825167ffffffffffffffff81111561047c5761047b6117e8565b5b6040519080825280602002602001820160405280156104aa5781602001602082028036833780820191505090505b50905060005b835181101561077a576104dc8482815181106104cf576104ce612505565b5b602002602001015161162c565b8282815181106104ef576104ee612505565b5b60200260200101901515908115158152505081818151811061051457610513612505565b5b60200260200101511561076d5760006001600286848151811061053a57610539612505565b5b602002602001015160405161054f91906121dc565b90815260200160405180910390205461056891906124d1565b90506001818154811061057e5761057d612505565b5b90600052602060002090600302016040518060600160405290816000820180546105a790612222565b80601f01602080910402602001604051908101604052809291908181526020018280546105d390612222565b80156106205780601f106105f557610100808354040283529160200191610620565b820191906000526020600020905b81548152906001019060200180831161060357829003601f168201915b5050505050815260200160018201805461063990612222565b80601f016020809104026020016040519081016040528092919081815260200182805461066590612222565b80156106b25780601f10610687576101008083540402835291602001916106b2565b820191906000526020600020905b81548152906001019060200180831161069557829003601f168201915b505050505081526020016002820180546106cb90612222565b80601f01602080910402602001604051908101604052809291908181526020018280546106f790612222565b80156107445780601f1061071957610100808354040283529160200191610744565b820191906000526020600020905b81548152906001019060200180831161072757829003601f168201915b5050505050815250508483815181106107605761075f612505565b5b6020026020010181905250505b80806001019150506104b0565b50915091565b60608060008080549050905080851061084057600067ffffffffffffffff8111156107ae576107ad6117e8565b5b6040519080825280602002602001820160405280156107e157816020015b60608152602001906001900390816107cc5790505b509250600067ffffffffffffffff8111156107ff576107fe6117e8565b5b60405190808252806020026020018201604052801561083857816020015b610825611657565b81526020019060019003908161081d5790505b509150610bfc565b6000858261084e91906124d1565b9050600081861161085f5785610861565b815b90508067ffffffffffffffff81111561087d5761087c6117e8565b5b6040519080825280602002602001820160405280156108b057816020015b606081526020019060019003908161089b5790505b5094508067ffffffffffffffff8111156108cd576108cc6117e8565b5b60405190808252806020026020018201604052801561090657816020015b6108f3611657565b8152602001906001900390816108eb5790505b50935060005b81811015610bf85760008189610922919061216c565b90506000818154811061093857610937612505565b5b90600052602060002001805461094d90612222565b80601f016020809104026020016040519081016040528092919081815260200182805461097990612222565b80156109c65780601f1061099b576101008083540402835291602001916109c6565b820191906000526020600020905b8154815290600101906020018083116109a957829003601f168201915b50505050508783815181106109de576109dd612505565b5b6020026020010181905250600181815481106109fd576109fc612505565b5b9060005260206000209060030201604051806060016040529081600082018054610a2690612222565b80601f0160208091040260200160405190810160405280929190818152602001828054610a5290612222565b8015610a9f5780601f10610a7457610100808354040283529160200191610a9f565b820191906000526020600020905b815481529060010190602001808311610a8257829003601f168201915b50505050508152602001600182018054610ab890612222565b80601f0160208091040260200160405190810160405280929190818152602001828054610ae490612222565b8015610b315780601f10610b0657610100808354040283529160200191610b31565b820191906000526020600020905b815481529060010190602001808311610b1457829003601f168201915b50505050508152602001600282018054610b4a90612222565b80601f0160208091040260200160405190810160405280929190818152602001828054610b7690612222565b8015610bc35780601f10610b9857610100808354040283529160200191610bc3565b820191906000526020600020905b815481529060010190602001808311610ba657829003601f168201915b505050505081525050868381518110610bdf57610bde612505565b5b602002602001018190525050808060010191505061090c565b5050505b9250925092565b60005b600080549050811015610ced576000808281548110610c2857610c27612505565b5b906000526020600020018054610c3d90612222565b80601f0160208091040260200160405190810160405280929190818152602001828054610c6990612222565b8015610cb65780601f10610c8b57610100808354040283529160200191610cb6565b820191906000526020600020905b815481529060010190602001808311610c9957829003601f168201915b50505050509050600281604051610ccd91906121dc565b908152602001604051809103902060009055508080600101915050610c06565b50600080610cfb9190611678565b60016000610d099190611699565b7f6c7e419df39ff46e811e7d979ebfd916b8d4960de06f479dc69cf8417cdb89e760405160405180910390a1565b610d408161162c565b610d7f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610d7690612580565b60405180910390fd5b60006001600283604051610d9391906121dc565b908152602001604051809103902054610dac91906124d1565b905060006001600080549050610dc291906124d1565b9050808214611122576000808281548110610de057610ddf612505565b5b906000526020600020018054610df590612222565b80601f0160208091040260200160405190810160405280929190818152602001828054610e2190612222565b8015610e6e5780601f10610e4357610100808354040283529160200191610e6e565b820191906000526020600020905b815481529060010190602001808311610e5157829003601f168201915b50505050509050600060018381548110610e8b57610e8a612505565b5b9060005260206000209060030201604051806060016040529081600082018054610eb490612222565b80601f0160208091040260200160405190810160405280929190818152602001828054610ee090612222565b8015610f2d5780601f10610f0257610100808354040283529160200191610f2d565b820191906000526020600020905b815481529060010190602001808311610f1057829003601f168201915b50505050508152602001600182018054610f4690612222565b80601f0160208091040260200160405190810160405280929190818152602001828054610f7290612222565b8015610fbf5780601f10610f9457610100808354040283529160200191610fbf565b820191906000526020600020905b815481529060010190602001808311610fa257829003601f168201915b50505050508152602001600282018054610fd890612222565b80601f016020809104026020016040519081016040528092919081815260200182805461100490612222565b80156110515780601f1061102657610100808354040283529160200191611051565b820191906000526020600020905b81548152906001019060200180831161103457829003601f168201915b5050505050815250509050816000858154811061107157611070612505565b5b90600052602060002001908161108791906123ff565b50806001858154811061109d5761109c612505565b5b906000526020600020906003020160008201518160000190816110c091906123ff565b5060208201518160010190816110d691906123ff565b5060408201518160020190816110ec91906123ff565b509050506001846110fd919061216c565b60028360405161110d91906121dc565b90815260200160405180910390208190555050505b6000805480611134576111336125a0565b5b60019003818190600052602060002001600061115091906116bd565b90556001805480611164576111636125a0565b5b60019003818190600052602060002090600302016000808201600061118991906116bd565b60018201600061119991906116bd565b6002820160006111a991906116bd565b505090556002836040516111bd91906121dc565b908152602001604051809103902060009055826040516111dd91906121dc565b60405180910390207f9248955bf73fd007be0a0d9dc13c36f9e61c3642fbac04d8ac592e0c21d0103760405160405180910390a2505050565b60006112218261162c565b9050919050565b606060008080549050905080841061129057600067ffffffffffffffff811115611255576112546117e8565b5b60405190808252806020026020018201604052801561128857816020015b60608152602001906001900390816112735790505b5091506113ef565b6000848261129e91906124d1565b905060008185116112af57846112b1565b815b90508067ffffffffffffffff8111156112cd576112cc6117e8565b5b60405190808252806020026020018201604052801561130057816020015b60608152602001906001900390816112eb5790505b50935060005b818110156113eb576000818861131c919061216c565b8154811061132d5761132c612505565b5b90600052602060002001805461134290612222565b80601f016020809104026020016040519081016040528092919081815260200182805461136e90612222565b80156113bb5780601f10611390576101008083540402835291602001916113bb565b820191906000526020600020905b81548152906001019060200180831161139e57829003601f168201915b50505050508582815181106113d3576113d2612505565b5b60200260200101819052508080600101915050611306565b5050505b9250929050565b6113fe611657565b60006114098361162c565b90508015611627576000600160028560405161142591906121dc565b90815260200160405180910390205461143e91906124d1565b90506001818154811061145457611453612505565b5b906000526020600020906003020160405180606001604052908160008201805461147d90612222565b80601f01602080910402602001604051908101604052809291908181526020018280546114a990612222565b80156114f65780601f106114cb576101008083540402835291602001916114f6565b820191906000526020600020905b8154815290600101906020018083116114d957829003601f168201915b5050505050815260200160018201805461150f90612222565b80601f016020809104026020016040519081016040528092919081815260200182805461153b90612222565b80156115885780601f1061155d57610100808354040283529160200191611588565b820191906000526020600020905b81548152906001019060200180831161156b57829003601f168201915b505050505081526020016002820180546115a190612222565b80601f01602080910402602001604051908101604052809291908181526020018280546115cd90612222565b801561161a5780601f106115ef5761010080835404028352916020019161161a565b820191906000526020600020905b8154815290600101906020018083116115fd57829003601f168201915b5050505050815250509250505b915091565b60008060028360405161163f91906121dc565b90815260200160405180910390205414159050919050565b60405180606001604052806060815260200160608152602001606081525090565b508054600082559060005260206000209081019061169691906116fd565b50565b50805460008255600302906000526020600020908101906116ba9190611721565b50565b5080546116c990612222565b6000825580601f106116db57506116fa565b601f0160209004906000526020600020908101906116f99190611768565b5b50565b5b8082111561171d576000818161171491906116bd565b506001016116fe565b5090565b5b80821115611764576000808201600061173b91906116bd565b60018201600061174b91906116bd565b60028201600061175b91906116bd565b50600301611722565b5090565b5b80821115611781576000816000905550600101611769565b5090565b6000819050919050565b61179881611785565b82525050565b60006020820190506117b3600083018461178f565b92915050565b6000604051905090565b600080fd5b600080fd5b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b611820826117d7565b810181811067ffffffffffffffff8211171561183f5761183e6117e8565b5b80604052505050565b60006118526117b9565b905061185e8282611817565b919050565b600067ffffffffffffffff82111561187e5761187d6117e8565b5b611887826117d7565b9050602081019050919050565b82818337600083830152505050565b60006118b66118b184611863565b611848565b9050828152602081018484840111156118d2576118d16117d2565b5b6118dd848285611894565b509392505050565b600082601f8301126118fa576118f96117cd565b5b813561190a8482602086016118a3565b91505092915050565b600080fd5b600080fd5b60006060828403121561193357611932611913565b5b61193d6060611848565b9050600082013567ffffffffffffffff81111561195d5761195c611918565b5b611969848285016118e5565b600083015250602082013567ffffffffffffffff81111561198d5761198c611918565b5b611999848285016118e5565b602083015250604082013567ffffffffffffffff8111156119bd576119bc611918565b5b6119c9848285016118e5565b60408301525092915050565b600080604083850312156119ec576119eb6117c3565b5b600083013567ffffffffffffffff811115611a0a57611a096117c8565b5b611a16858286016118e5565b925050602083013567ffffffffffffffff811115611a3757611a366117c8565b5b611a438582860161191d565b9150509250929050565b600067ffffffffffffffff821115611a6857611a676117e8565b5b602082029050602081019050919050565b600080fd5b6000611a91611a8c84611a4d565b611848565b90508083825260208201905060208402830185811115611ab457611ab3611a79565b5b835b81811015611afb57803567ffffffffffffffff811115611ad957611ad86117cd565b5b808601611ae689826118e5565b85526020850194505050602081019050611ab6565b5050509392505050565b600082601f830112611b1a57611b196117cd565b5b8135611b2a848260208601611a7e565b91505092915050565b600060208284031215611b4957611b486117c3565b5b600082013567ffffffffffffffff811115611b6757611b666117c8565b5b611b7384828501611b05565b91505092915050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b600081519050919050565b600082825260208201905092915050565b60005b83811015611be2578082015181840152602081019050611bc7565b60008484015250505050565b6000611bf982611ba8565b611c038185611bb3565b9350611c13818560208601611bc4565b611c1c816117d7565b840191505092915050565b60006060830160008301518482036000860152611c448282611bee565b91505060208301518482036020860152611c5e8282611bee565b91505060408301518482036040860152611c788282611bee565b9150508091505092915050565b6000611c918383611c27565b905092915050565b6000602082019050919050565b6000611cb182611b7c565b611cbb8185611b87565b935083602082028501611ccd85611b98565b8060005b85811015611d095784840389528151611cea8582611c85565b9450611cf583611c99565b925060208a01995050600181019050611cd1565b50829750879550505050505092915050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b60008115159050919050565b611d5c81611d47565b82525050565b6000611d6e8383611d53565b60208301905092915050565b6000602082019050919050565b6000611d9282611d1b565b611d9c8185611d26565b9350611da783611d37565b8060005b83811015611dd8578151611dbf8882611d62565b9750611dca83611d7a565b925050600181019050611dab565b5085935050505092915050565b60006040820190508181036000830152611dff8185611ca6565b90508181036020830152611e138184611d87565b90509392505050565b611e2581611785565b8114611e3057600080fd5b50565b600081359050611e4281611e1c565b92915050565b60008060408385031215611e5f57611e5e6117c3565b5b6000611e6d85828601611e33565b9250506020611e7e85828601611e33565b9150509250929050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b6000611ec08383611bee565b905092915050565b6000602082019050919050565b6000611ee082611e88565b611eea8185611e93565b935083602082028501611efc85611ea4565b8060005b85811015611f385784840389528151611f198582611eb4565b9450611f2483611ec8565b925060208a01995050600181019050611f00565b50829750879550505050505092915050565b60006060820190508181036000830152611f648186611ed5565b90508181036020830152611f788185611ca6565b9050611f87604083018461178f565b949350505050565b600060208284031215611fa557611fa46117c3565b5b600082013567ffffffffffffffff811115611fc357611fc26117c8565b5b611fcf848285016118e5565b91505092915050565b611fe181611d47565b82525050565b6000602082019050611ffc6000830184611fd8565b92915050565b6000604082019050818103600083015261201c8185611ed5565b905061202b602083018461178f565b9392505050565b6000606083016000830151848203600086015261204f8282611bee565b915050602083015184820360208601526120698282611bee565b915050604083015184820360408601526120838282611bee565b9150508091505092915050565b600060408201905081810360008301526120aa8185612032565b90506120b96020830184611fd8565b9392505050565b600082825260208201905092915050565b7f4b65792063616e6e6f7420626520656d70747900000000000000000000000000600082015250565b60006121076013836120c0565b9150612112826120d1565b602082019050919050565b60006020820190508181036000830152612136816120fa565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600061217782611785565b915061218283611785565b925082820190508082111561219a5761219961213d565b5b92915050565b600081905092915050565b60006121b682611ba8565b6121c081856121a0565b93506121d0818560208601611bc4565b80840191505092915050565b60006121e882846121ab565b915081905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b6000600282049050600182168061223a57607f821691505b60208210810361224d5761224c6121f3565b5b50919050565b60008190508160005260206000209050919050565b60006020601f8301049050919050565b600082821b905092915050565b6000600883026122b57fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82612278565b6122bf8683612278565b95508019841693508086168417925050509392505050565b6000819050919050565b60006122fc6122f76122f284611785565b6122d7565b611785565b9050919050565b6000819050919050565b612316836122e1565b61232a61232282612303565b848454612285565b825550505050565b600090565b61233f612332565b61234a81848461230d565b505050565b5b8181101561236e57612363600082612337565b600181019050612350565b5050565b601f8211156123b35761238481612253565b61238d84612268565b8101602085101561239c578190505b6123b06123a885612268565b83018261234f565b50505b505050565b600082821c905092915050565b60006123d6600019846008026123b8565b1980831691505092915050565b60006123ef83836123c5565b9150826002028217905092915050565b61240882611ba8565b67ffffffffffffffff811115612421576124206117e8565b5b61242b8254612222565b612436828285612372565b600060209050601f8311600181146124695760008415612457578287015190505b61246185826123e3565b8655506124c9565b601f19841661247786612253565b60005b8281101561249f5784890151825560018201915060208501945060208101905061247a565b868310156124bc57848901516124b8601f8916826123c5565b8355505b6001600288020188555050505b505050505050565b60006124dc82611785565b91506124e783611785565b92508282039050818111156124ff576124fe61213d565b5b92915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4b657920646f6573206e6f742065786973740000000000000000000000000000600082015250565b600061256a6012836120c0565b915061257582612534565b602082019050919050565b600060208201905081810360008301526125998161255d565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fdfea26469706673582212206d7a7be588de9e5b02bffc80ea79dfdbc24ce443849bc498f8f3e36fe69acf0f64736f6c63430008180033" diff --git a/systemcontracts/namespace_storage_abi.go b/systemcontracts/namespace_storage_abi.go index da1745c18e..1d65ecea06 100644 --- a/systemcontracts/namespace_storage_abi.go +++ b/systemcontracts/namespace_storage_abi.go @@ -503,4 +503,4 @@ const NamespaceStorageABI = `[ ]` // NamespaceStorageContractByteCodeStr is the bytecode for the NamespaceStorage contract -const NamespaceStorageContractByteCodeStr = "608060405234801561001057600080fd5b50613df1806100206000396000f3fe608060405234801561001057600080fd5b50600436106100f55760003560e01c8063912f309511610097578063c9037d2d11610066578063c9037d2d146102b1578063d1e96865146102e1578063ebb689a114610311578063f53504231461031b576100f5565b8063912f309514610214578063a2bc7a1c14610246578063aff6274514610262578063b40ec02b14610293576100f5565b80634b6b9a8c116100d35780634b6b9a8c146101655780634e8bfabb1461019657806353df2b27146101b257806370eafd18146101e4576100f5565b806304e52369146100fa57806312862f7f1461011657806334eafb1114610147575b600080fd5b610114600480360381019061010f91906126b3565b610337565b005b610130600480360381019061012b9190612811565b61064f565b60405161013e929190612af2565b60405180910390f35b61014f6109f1565b60405161015c9190612b42565b60405180910390f35b61017f600480360381019061017a9190612b89565b610a63565b60405161018d929190612cba565b60405180910390f35b6101b060048036038101906101ab9190612e8d565b610c54565b005b6101cc60048036038101906101c79190612f34565b61105b565b6040516101db93929190613149565b60405180910390f35b6101fe60048036038101906101f9919061318e565b611309565b60405161020b91906131e6565b60405180910390f35b61022e60048036038101906102299190612b89565b61133e565b60405161023d93929190613201565b60405180910390f35b610260600480360381019061025b919061318e565b6117fd565b005b61027c600480360381019061027791906126b3565b611a82565b60405161028a9291906132a4565b60405180910390f35b61029b611ce1565b6040516102a89190612b42565b60405180910390f35b6102cb60048036038101906102c6919061318e565b611cee565b6040516102d89190612b42565b60405180910390f35b6102fb60048036038101906102f691906126b3565b611d19565b60405161030891906131e6565b60405180910390f35b610319611d6b565b005b610335600480360381019061033091906132d4565b61207d565b005b60048260405161034791906133b7565b908152602001604051809103902060009054906101000a900460ff166103a2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103999061342b565b60405180910390fd5b6002826040516103b291906133b7565b9081526020016040518091039020816040516103ce9190613487565b908152602001604051809103902060009054906101000a900460ff16610429576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610420906134ea565b60405180910390fd5b60008260405161043991906133b7565b9081526020016040518091039020816040516104559190613487565b9081526020016040518091039020600080820160006104749190612370565b6001820160006104849190612370565b6002820160006104949190612370565b505060006002836040516104a891906133b7565b9081526020016040518091039020826040516104c49190613487565b908152602001604051809103902060006101000a81548160ff02191690831515021790555060006001836040516104fb91906133b7565b9081526020016040518091039020905060005b81805490508110156105f15782805190602001208282815481106105355761053461350a565b5b9060005260206000200160405161054c9190613631565b6040518091039020036105e457816001838054905061056b9190613677565b8154811061057c5761057b61350a565b5b906000526020600020018282815481106105995761059861350a565b5b9060005260206000200190816105af919061386d565b50818054806105c1576105c0613955565b5b6001900381819060005260206000200160006105dd9190612370565b90556105f1565b808060010191505061050e565b50816040516106009190613487565b60405180910390208360405161061691906133b7565b60405180910390207faf8967c7b21227d5d987c31cd064433b027cf5bd93330cdbe6b62909093c417260405160405180910390a3505050565b606080825167ffffffffffffffff81111561066d5761066c6124e7565b5b6040519080825280602002602001820160405280156106a657816020015b6106936123b0565b81526020019060019003908161068b5790505b509150825167ffffffffffffffff8111156106c4576106c36124e7565b5b6040519080825280602002602001820160405280156106f25781602001602082028036833780820191505090505b50905060005b83518110156109e95760028560405161071191906133b7565b90815260200160405180910390208482815181106107325761073161350a565b5b60200260200101516040516107479190613487565b908152602001604051809103902060009054906101000a900460ff168282815181106107765761077561350a565b5b60200260200101901515908115158152505081818151811061079b5761079a61350a565b5b6020026020010151156109dc576000856040516107b891906133b7565b90815260200160405180910390208482815181106107d9576107d861350a565b5b60200260200101516040516107ee9190613487565b908152602001604051809103902060405180606001604052908160008201805461081790613568565b80601f016020809104026020016040519081016040528092919081815260200182805461084390613568565b80156108905780601f1061086557610100808354040283529160200191610890565b820191906000526020600020905b81548152906001019060200180831161087357829003601f168201915b505050505081526020016001820180546108a990613568565b80601f01602080910402602001604051908101604052809291908181526020018280546108d590613568565b80156109225780601f106108f757610100808354040283529160200191610922565b820191906000526020600020905b81548152906001019060200180831161090557829003601f168201915b5050505050815260200160028201805461093b90613568565b80601f016020809104026020016040519081016040528092919081815260200182805461096790613568565b80156109b45780601f10610989576101008083540402835291602001916109b4565b820191906000526020600020905b81548152906001019060200180831161099757829003601f168201915b5050505050815250508382815181106109d0576109cf61350a565b5b60200260200101819052505b80806001019150506106f8565b509250929050565b600080600090505b600380549050811015610a5f57600160038281548110610a1c57610a1b61350a565b5b90600052602060002001604051610a339190613a1c565b90815260200160405180910390208054905082610a509190613a33565b915080806001019150506109f9565b5090565b6060600080600186604051610a7891906133b7565b9081526020016040518091039020905080805490509150818510610aed57600067ffffffffffffffff811115610ab157610ab06124e7565b5b604051908082528060200260200182016040528015610ae457816020015b6060815260200190600190039081610acf5790505b50925050610c4c565b60008583610afb9190613677565b90506000818611610b0c5785610b0e565b815b90508067ffffffffffffffff811115610b2a57610b296124e7565b5b604051908082528060200260200182016040528015610b5d57816020015b6060815260200190600190039081610b485790505b50945060005b81811015610c4757838189610b789190613a33565b81548110610b8957610b8861350a565b5b906000526020600020018054610b9e90613568565b80601f0160208091040260200160405190810160405280929190818152602001828054610bca90613568565b8015610c175780601f10610bec57610100808354040283529160200191610c17565b820191906000526020600020905b815481529060010190602001808311610bfa57829003601f168201915b5050505050868281518110610c2f57610c2e61350a565b5b60200260200101819052508080600101915050610b63565b505050505b935093915050565b8051825114610c98576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610c8f90613ad9565b60405180910390fd5b6000835111610cdc576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610cd390613b45565b60405180910390fd5b600483604051610cec91906133b7565b908152602001604051809103902060009054906101000a900460ff16610d7957600383908060018154018082558091505060019003906000526020600020016000909190919091509081610d409190613bab565b506001600484604051610d5391906133b7565b908152602001604051809103902060006101000a81548160ff0219169083151502179055505b60005b8251811015611055576000838281518110610d9a57610d9961350a565b5b60200260200101515111610de3576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610dda90613cc9565b60405180910390fd5b600284604051610df391906133b7565b9081526020016040518091039020838281518110610e1457610e1361350a565b5b6020026020010151604051610e299190613487565b908152602001604051809103902060009054906101000a900460ff16610f2257600184604051610e5991906133b7565b9081526020016040518091039020838281518110610e7a57610e7961350a565b5b6020026020010151908060018154018082558091505060019003906000526020600020016000909190919091509081610eb39190613ce9565b506001600285604051610ec691906133b7565b9081526020016040518091039020848381518110610ee757610ee661350a565b5b6020026020010151604051610efc9190613487565b908152602001604051809103902060006101000a81548160ff0219169083151502179055505b818181518110610f3557610f3461350a565b5b6020026020010151600085604051610f4d91906133b7565b9081526020016040518091039020848381518110610f6e57610f6d61350a565b5b6020026020010151604051610f839190613487565b90815260200160405180910390206000820151816000019081610fa69190613ce9565b506020820151816001019081610fbc9190613ce9565b506040820151816002019081610fd29190613ce9565b50905050828181518110610fe957610fe861350a565b5b6020026020010151604051610ffe9190613487565b60405180910390208460405161101491906133b7565b60405180910390207fd00871f87cd1b1b4e50e5be511f060478c06a013856673c392f2adbfa65df8ad60405160405180910390a38080600101915050610d7c565b50505050565b6060806000600380549050905080851061111157600067ffffffffffffffff81111561108a576110896124e7565b5b6040519080825280602002602001820160405280156110bd57816020015b60608152602001906001900390816110a85790505b509250600067ffffffffffffffff8111156110db576110da6124e7565b5b6040519080825280602002602001820160405280156111095781602001602082028036833780820191505090505b509150611302565b6000858261111f9190613677565b905060008186116111305785611132565b815b90508067ffffffffffffffff81111561114e5761114d6124e7565b5b60405190808252806020026020018201604052801561118157816020015b606081526020019060019003908161116c5790505b5094508067ffffffffffffffff81111561119e5761119d6124e7565b5b6040519080825280602002602001820160405280156111cc5781602001602082028036833780820191505090505b50935060005b818110156112fe5760006003828a6111ea9190613a33565b815481106111fb576111fa61350a565b5b90600052602060002001805461121090613568565b80601f016020809104026020016040519081016040528092919081815260200182805461123c90613568565b80156112895780601f1061125e57610100808354040283529160200191611289565b820191906000526020600020905b81548152906001019060200180831161126c57829003601f168201915b50505050509050808783815181106112a4576112a361350a565b5b60200260200101819052506001816040516112bf91906133b7565b9081526020016040518091039020805490508683815181106112e4576112e361350a565b5b6020026020010181815250505080806001019150506111d2565b5050505b9250925092565b600060048260405161131b91906133b7565b908152602001604051809103902060009054906101000a900460ff169050919050565b60608060008060018760405161135491906133b7565b908152602001604051809103902090508080549050915081861061142057600067ffffffffffffffff81111561138d5761138c6124e7565b5b6040519080825280602002602001820160405280156113c057816020015b60608152602001906001900390816113ab5790505b509350600067ffffffffffffffff8111156113de576113dd6124e7565b5b60405190808252806020026020018201604052801561141757816020015b6114046123b0565b8152602001906001900390816113fc5790505b509250506117f4565b6000868361142e9190613677565b9050600081871161143f5786611441565b815b90508067ffffffffffffffff81111561145d5761145c6124e7565b5b60405190808252806020026020018201604052801561149057816020015b606081526020019060019003908161147b5790505b5095508067ffffffffffffffff8111156114ad576114ac6124e7565b5b6040519080825280602002602001820160405280156114e657816020015b6114d36123b0565b8152602001906001900390816114cb5790505b50945060005b818110156117ef57600084828b6115039190613a33565b815481106115145761151361350a565b5b90600052602060002001805461152990613568565b80601f016020809104026020016040519081016040528092919081815260200182805461155590613568565b80156115a25780601f10611577576101008083540402835291602001916115a2565b820191906000526020600020905b81548152906001019060200180831161158557829003601f168201915b50505050509050808883815181106115bd576115bc61350a565b5b602002602001018190525060008b6040516115d891906133b7565b9081526020016040518091039020816040516115f49190613487565b908152602001604051809103902060405180606001604052908160008201805461161d90613568565b80601f016020809104026020016040519081016040528092919081815260200182805461164990613568565b80156116965780601f1061166b57610100808354040283529160200191611696565b820191906000526020600020905b81548152906001019060200180831161167957829003601f168201915b505050505081526020016001820180546116af90613568565b80601f01602080910402602001604051908101604052809291908181526020018280546116db90613568565b80156117285780601f106116fd57610100808354040283529160200191611728565b820191906000526020600020905b81548152906001019060200180831161170b57829003601f168201915b5050505050815260200160028201805461174190613568565b80601f016020809104026020016040519081016040528092919081815260200182805461176d90613568565b80156117ba5780601f1061178f576101008083540402835291602001916117ba565b820191906000526020600020905b81548152906001019060200180831161179d57829003601f168201915b5050505050815250508783815181106117d6576117d561350a565b5b60200260200101819052505080806001019150506114ec565b505050505b93509350939050565b60048160405161180d91906133b7565b908152602001604051809103902060009054906101000a900460ff16611868576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161185f9061342b565b60405180910390fd5b600060018260405161187a91906133b7565b9081526020016040518091039020905060005b8180549050811015611a115760008282815481106118ae576118ad61350a565b5b9060005260206000200180546118c390613568565b80601f01602080910402602001604051908101604052809291908181526020018280546118ef90613568565b801561193c5780601f106119115761010080835404028352916020019161193c565b820191906000526020600020905b81548152906001019060200180831161191f57829003601f168201915b5050505050905060008460405161195391906133b7565b90815260200160405180910390208160405161196f9190613487565b90815260200160405180910390206000808201600061198e9190612370565b60018201600061199e9190612370565b6002820160006119ae9190612370565b505060006002856040516119c291906133b7565b9081526020016040518091039020826040516119de9190613487565b908152602001604051809103902060006101000a81548160ff02191690831515021790555050808060010191505061188d565b50600182604051611a2291906133b7565b90815260200160405180910390206000611a3c91906123d1565b81604051611a4a91906133b7565b60405180910390207f372dd188f66e03080f62fc207ebf4954a98c81128ca2472aedfc273f0f7c788360405160405180910390a25050565b611a8a6123b0565b6000600284604051611a9c91906133b7565b908152602001604051809103902083604051611ab89190613487565b908152602001604051809103902060009054906101000a900460ff1690508015611cda57600084604051611aec91906133b7565b908152602001604051809103902083604051611b089190613487565b9081526020016040518091039020604051806060016040529081600082018054611b3190613568565b80601f0160208091040260200160405190810160405280929190818152602001828054611b5d90613568565b8015611baa5780601f10611b7f57610100808354040283529160200191611baa565b820191906000526020600020905b815481529060010190602001808311611b8d57829003601f168201915b50505050508152602001600182018054611bc390613568565b80601f0160208091040260200160405190810160405280929190818152602001828054611bef90613568565b8015611c3c5780601f10611c1157610100808354040283529160200191611c3c565b820191906000526020600020905b815481529060010190602001808311611c1f57829003601f168201915b50505050508152602001600282018054611c5590613568565b80601f0160208091040260200160405190810160405280929190818152602001828054611c8190613568565b8015611cce5780601f10611ca357610100808354040283529160200191611cce565b820191906000526020600020905b815481529060010190602001808311611cb157829003601f168201915b50505050508152505091505b9250929050565b6000600380549050905090565b6000600182604051611d0091906133b7565b9081526020016040518091039020805490509050919050565b6000600283604051611d2b91906133b7565b908152602001604051809103902082604051611d479190613487565b908152602001604051809103902060009054906101000a900460ff16905092915050565b60005b60038054905081101561204057600060038281548110611d9157611d9061350a565b5b906000526020600020018054611da690613568565b80601f0160208091040260200160405190810160405280929190818152602001828054611dd290613568565b8015611e1f5780601f10611df457610100808354040283529160200191611e1f565b820191906000526020600020905b815481529060010190602001808311611e0257829003601f168201915b505050505090506000600182604051611e3891906133b7565b9081526020016040518091039020905060005b8180549050811015611fcf576000828281548110611e6c57611e6b61350a565b5b906000526020600020018054611e8190613568565b80601f0160208091040260200160405190810160405280929190818152602001828054611ead90613568565b8015611efa5780601f10611ecf57610100808354040283529160200191611efa565b820191906000526020600020905b815481529060010190602001808311611edd57829003601f168201915b50505050509050600084604051611f1191906133b7565b908152602001604051809103902081604051611f2d9190613487565b908152602001604051809103902060008082016000611f4c9190612370565b600182016000611f5c9190612370565b600282016000611f6c9190612370565b50506000600285604051611f8091906133b7565b908152602001604051809103902082604051611f9c9190613487565b908152602001604051809103902060006101000a81548160ff021916908315150217905550508080600101915050611e4b565b50600182604051611fe091906133b7565b90815260200160405180910390206000611ffa91906123d1565b600060048360405161200c91906133b7565b908152602001604051809103902060006101000a81548160ff02191690831515021790555050508080600101915050611d6e565b506003600061204f91906123f2565b7f30addec5e9e954699f286bae8e1558655b0d436c3d7b501014eb5c0b4a76e6db60405160405180910390a1565b60008351116120c1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016120b890613b45565b60405180910390fd5b6000825111612105576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016120fc90613cc9565b60405180910390fd5b60048360405161211591906133b7565b908152602001604051809103902060009054906101000a900460ff166121a2576003839080600181540180825580915050600190039060005260206000200160009091909190915090816121699190613bab565b50600160048460405161217c91906133b7565b908152602001604051809103902060006101000a81548160ff0219169083151502179055505b6002836040516121b291906133b7565b9081526020016040518091039020826040516121ce9190613487565b908152602001604051809103902060009054906101000a900460ff16612293576001836040516121fe91906133b7565b90815260200160405180910390208290806001815401808255809150506001900390600052602060002001600090919091909150908161223e9190613ce9565b50600160028460405161225191906133b7565b90815260200160405180910390208360405161226d9190613487565b908152602001604051809103902060006101000a81548160ff0219169083151502179055505b806000846040516122a491906133b7565b9081526020016040518091039020836040516122c09190613487565b908152602001604051809103902060008201518160000190816122e39190613ce9565b5060208201518160010190816122f99190613ce9565b50604082015181600201908161230f9190613ce9565b50905050816040516123219190613487565b60405180910390208360405161233791906133b7565b60405180910390207fd00871f87cd1b1b4e50e5be511f060478c06a013856673c392f2adbfa65df8ad60405160405180910390a3505050565b50805461237c90613568565b6000825580601f1061238e57506123ad565b601f0160209004906000526020600020908101906123ac9190612413565b5b50565b60405180606001604052806060815260200160608152602001606081525090565b50805460008255906000526020600020908101906123ef9190612430565b50565b50805460008255906000526020600020908101906124109190612454565b50565b5b8082111561242c576000816000905550600101612414565b5090565b5b8082111561245057600081816124479190612370565b50600101612431565b5090565b5b80821115612474576000818161246b9190612478565b50600101612455565b5090565b50805461248490613568565b6000825580601f1061249657506124b5565b601f0160209004906000526020600020908101906124b49190612413565b5b50565b6000604051905090565b600080fd5b600080fd5b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b61251f826124d6565b810181811067ffffffffffffffff8211171561253e5761253d6124e7565b5b80604052505050565b60006125516124b8565b905061255d8282612516565b919050565b600067ffffffffffffffff82111561257d5761257c6124e7565b5b612586826124d6565b9050602081019050919050565b82818337600083830152505050565b60006125b56125b084612562565b612547565b9050828152602081018484840111156125d1576125d06124d1565b5b6125dc848285612593565b509392505050565b600082601f8301126125f9576125f86124cc565b5b81356126098482602086016125a2565b91505092915050565b600067ffffffffffffffff82111561262d5761262c6124e7565b5b612636826124d6565b9050602081019050919050565b600061265661265184612612565b612547565b905082815260208101848484011115612672576126716124d1565b5b61267d848285612593565b509392505050565b600082601f83011261269a576126996124cc565b5b81356126aa848260208601612643565b91505092915050565b600080604083850312156126ca576126c96124c2565b5b600083013567ffffffffffffffff8111156126e8576126e76124c7565b5b6126f4858286016125e4565b925050602083013567ffffffffffffffff811115612715576127146124c7565b5b61272185828601612685565b9150509250929050565b600067ffffffffffffffff821115612746576127456124e7565b5b602082029050602081019050919050565b600080fd5b600061276f61276a8461272b565b612547565b9050808382526020820190506020840283018581111561279257612791612757565b5b835b818110156127d957803567ffffffffffffffff8111156127b7576127b66124cc565b5b8086016127c48982612685565b85526020850194505050602081019050612794565b5050509392505050565b600082601f8301126127f8576127f76124cc565b5b813561280884826020860161275c565b91505092915050565b60008060408385031215612828576128276124c2565b5b600083013567ffffffffffffffff811115612846576128456124c7565b5b612852858286016125e4565b925050602083013567ffffffffffffffff811115612873576128726124c7565b5b61287f858286016127e3565b9150509250929050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b600081519050919050565b600082825260208201905092915050565b60005b838110156128ef5780820151818401526020810190506128d4565b60008484015250505050565b6000612906826128b5565b61291081856128c0565b93506129208185602086016128d1565b612929816124d6565b840191505092915050565b6000606083016000830151848203600086015261295182826128fb565b9150506020830151848203602086015261296b82826128fb565b9150506040830151848203604086015261298582826128fb565b9150508091505092915050565b600061299e8383612934565b905092915050565b6000602082019050919050565b60006129be82612889565b6129c88185612894565b9350836020820285016129da856128a5565b8060005b85811015612a1657848403895281516129f78582612992565b9450612a02836129a6565b925060208a019950506001810190506129de565b50829750879550505050505092915050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b60008115159050919050565b612a6981612a54565b82525050565b6000612a7b8383612a60565b60208301905092915050565b6000602082019050919050565b6000612a9f82612a28565b612aa98185612a33565b9350612ab483612a44565b8060005b83811015612ae5578151612acc8882612a6f565b9750612ad783612a87565b925050600181019050612ab8565b5085935050505092915050565b60006040820190508181036000830152612b0c81856129b3565b90508181036020830152612b208184612a94565b90509392505050565b6000819050919050565b612b3c81612b29565b82525050565b6000602082019050612b576000830184612b33565b92915050565b612b6681612b29565b8114612b7157600080fd5b50565b600081359050612b8381612b5d565b92915050565b600080600060608486031215612ba257612ba16124c2565b5b600084013567ffffffffffffffff811115612bc057612bbf6124c7565b5b612bcc868287016125e4565b9350506020612bdd86828701612b74565b9250506040612bee86828701612b74565b9150509250925092565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b6000612c3083836128fb565b905092915050565b6000602082019050919050565b6000612c5082612bf8565b612c5a8185612c03565b935083602082028501612c6c85612c14565b8060005b85811015612ca85784840389528151612c898582612c24565b9450612c9483612c38565b925060208a01995050600181019050612c70565b50829750879550505050505092915050565b60006040820190508181036000830152612cd48185612c45565b9050612ce36020830184612b33565b9392505050565b600067ffffffffffffffff821115612d0557612d046124e7565b5b602082029050602081019050919050565b600080fd5b600080fd5b600060608284031215612d3657612d35612d16565b5b612d406060612547565b9050600082013567ffffffffffffffff811115612d6057612d5f612d1b565b5b612d6c84828501612685565b600083015250602082013567ffffffffffffffff811115612d9057612d8f612d1b565b5b612d9c84828501612685565b602083015250604082013567ffffffffffffffff811115612dc057612dbf612d1b565b5b612dcc84828501612685565b60408301525092915050565b6000612deb612de684612cea565b612547565b90508083825260208201905060208402830185811115612e0e57612e0d612757565b5b835b81811015612e5557803567ffffffffffffffff811115612e3357612e326124cc565b5b808601612e408982612d20565b85526020850194505050602081019050612e10565b5050509392505050565b600082601f830112612e7457612e736124cc565b5b8135612e84848260208601612dd8565b91505092915050565b600080600060608486031215612ea657612ea56124c2565b5b600084013567ffffffffffffffff811115612ec457612ec36124c7565b5b612ed0868287016125e4565b935050602084013567ffffffffffffffff811115612ef157612ef06124c7565b5b612efd868287016127e3565b925050604084013567ffffffffffffffff811115612f1e57612f1d6124c7565b5b612f2a86828701612e5f565b9150509250925092565b60008060408385031215612f4b57612f4a6124c2565b5b6000612f5985828601612b74565b9250506020612f6a85828601612b74565b9150509250929050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b600081519050919050565b600082825260208201905092915050565b6000612fc782612fa0565b612fd18185612fab565b9350612fe18185602086016128d1565b612fea816124d6565b840191505092915050565b60006130018383612fbc565b905092915050565b6000602082019050919050565b600061302182612f74565b61302b8185612f7f565b93508360208202850161303d85612f90565b8060005b85811015613079578484038952815161305a8582612ff5565b945061306583613009565b925060208a01995050600181019050613041565b50829750879550505050505092915050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b6130c081612b29565b82525050565b60006130d283836130b7565b60208301905092915050565b6000602082019050919050565b60006130f68261308b565b6131008185613096565b935061310b836130a7565b8060005b8381101561313c57815161312388826130c6565b975061312e836130de565b92505060018101905061310f565b5085935050505092915050565b600060608201905081810360008301526131638186613016565b9050818103602083015261317781856130eb565b90506131866040830184612b33565b949350505050565b6000602082840312156131a4576131a36124c2565b5b600082013567ffffffffffffffff8111156131c2576131c16124c7565b5b6131ce848285016125e4565b91505092915050565b6131e081612a54565b82525050565b60006020820190506131fb60008301846131d7565b92915050565b6000606082019050818103600083015261321b8186612c45565b9050818103602083015261322f81856129b3565b905061323e6040830184612b33565b949350505050565b6000606083016000830151848203600086015261326382826128fb565b9150506020830151848203602086015261327d82826128fb565b9150506040830151848203604086015261329782826128fb565b9150508091505092915050565b600060408201905081810360008301526132be8185613246565b90506132cd60208301846131d7565b9392505050565b6000806000606084860312156132ed576132ec6124c2565b5b600084013567ffffffffffffffff81111561330b5761330a6124c7565b5b613317868287016125e4565b935050602084013567ffffffffffffffff811115613338576133376124c7565b5b61334486828701612685565b925050604084013567ffffffffffffffff811115613365576133646124c7565b5b61337186828701612d20565b9150509250925092565b600081905092915050565b600061339182612fa0565b61339b818561337b565b93506133ab8185602086016128d1565b80840191505092915050565b60006133c38284613386565b915081905092915050565b600082825260208201905092915050565b7f4e616d65737061636520646f6573206e6f742065786973740000000000000000600082015250565b60006134156018836133ce565b9150613420826133df565b602082019050919050565b6000602082019050818103600083015261344481613408565b9050919050565b600081905092915050565b6000613461826128b5565b61346b818561344b565b935061347b8185602086016128d1565b80840191505092915050565b60006134938284613456565b915081905092915050565b7f4b657920646f6573206e6f7420657869737420696e206e616d65737061636500600082015250565b60006134d4601f836133ce565b91506134df8261349e565b602082019050919050565b60006020820190508181036000830152613503816134c7565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b6000600282049050600182168061358057607f821691505b60208210810361359357613592613539565b5b50919050565b60008190508160005260206000209050919050565b600081546135bb81613568565b6135c5818661344b565b945060018216600081146135e057600181146135f557613628565b60ff1983168652811515820286019350613628565b6135fe85613599565b60005b8381101561362057815481890152600182019150602081019050613601565b838801955050505b50505092915050565b600061363d82846135ae565b915081905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600061368282612b29565b915061368d83612b29565b92508282039050818111156136a5576136a4613648565b5b92915050565b6000815490506136ba81613568565b9050919050565b60008190508160005260206000209050919050565b60006020601f8301049050919050565b600082821b905092915050565b6000600883026137237fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff826136e6565b61372d86836136e6565b95508019841693508086168417925050509392505050565b6000819050919050565b600061376a61376561376084612b29565b613745565b612b29565b9050919050565b6000819050919050565b6137848361374f565b61379861379082613771565b8484546136f3565b825550505050565b600090565b6137ad6137a0565b6137b881848461377b565b505050565b5b818110156137dc576137d16000826137a5565b6001810190506137be565b5050565b601f821115613821576137f281613599565b6137fb846136d6565b8101602085101561380a578190505b61381e613816856136d6565b8301826137bd565b50505b505050565b600082821c905092915050565b600061384460001984600802613826565b1980831691505092915050565b600061385d8383613833565b9150826002028217905092915050565b81810361387b575050613953565b613884826136ab565b67ffffffffffffffff81111561389d5761389c6124e7565b5b6138a78254613568565b6138b28282856137e0565b6000601f8311600181146138e157600084156138cf578287015490505b6138d98582613851565b86555061394c565b601f1984166138ef876136c1565b96506138fa86613599565b60005b82811015613922578489015482556001820191506001850194506020810190506138fd565b8683101561393f578489015461393b601f891682613833565b8355505b6001600288020188555050505b5050505050505b565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b60008190508160005260206000209050919050565b600081546139a681613568565b6139b0818661337b565b945060018216600081146139cb57600181146139e057613a13565b60ff1983168652811515820286019350613a13565b6139e985613984565b60005b83811015613a0b578154818901526001820191506020810190506139ec565b838801955050505b50505092915050565b6000613a288284613999565b915081905092915050565b6000613a3e82612b29565b9150613a4983612b29565b9250828201905080821115613a6157613a60613648565b5b92915050565b7f4b65797320616e642076616c75657320617272617973206d757374206861766560008201527f2073616d65206c656e6774680000000000000000000000000000000000000000602082015250565b6000613ac3602c836133ce565b9150613ace82613a67565b604082019050919050565b60006020820190508181036000830152613af281613ab6565b9050919050565b7f4e616d6573706163652063616e6e6f7420626520656d70747900000000000000600082015250565b6000613b2f6019836133ce565b9150613b3a82613af9565b602082019050919050565b60006020820190508181036000830152613b5e81613b22565b9050919050565b601f821115613ba657613b7781613984565b613b80846136d6565b81016020851015613b8f578190505b613ba3613b9b856136d6565b8301826137bd565b50505b505050565b613bb482612fa0565b67ffffffffffffffff811115613bcd57613bcc6124e7565b5b613bd78254613568565b613be2828285613b65565b600060209050601f831160018114613c155760008415613c03578287015190505b613c0d8582613851565b865550613c75565b601f198416613c2386613984565b60005b82811015613c4b57848901518255600182019150602085019450602081019050613c26565b86831015613c685784890151613c64601f891682613833565b8355505b6001600288020188555050505b505050505050565b7f4b65792063616e6e6f7420626520656d70747900000000000000000000000000600082015250565b6000613cb36013836133ce565b9150613cbe82613c7d565b602082019050919050565b60006020820190508181036000830152613ce281613ca6565b9050919050565b613cf2826128b5565b67ffffffffffffffff811115613d0b57613d0a6124e7565b5b613d158254613568565b613d208282856137e0565b600060209050601f831160018114613d535760008415613d41578287015190505b613d4b8582613851565b865550613db3565b601f198416613d6186613599565b60005b82811015613d8957848901518255600182019150602085019450602081019050613d64565b86831015613da65784890151613da2601f891682613833565b8355505b6001600288020188555050505b50505050505056fea264697066735822122010e6a669447af75331d35ed4f9d0505114fdea36140b19387ecd7764e89d732064736f6c63430008180033" +const NamespaceStorageContractByteCodeStr = "608060405234801561001057600080fd5b50614122806100206000396000f3fe608060405234801561001057600080fd5b50600436106100f55760003560e01c8063912f309511610097578063c9037d2d11610066578063c9037d2d146102b1578063d1e96865146102e1578063ebb689a114610311578063f53504231461031b576100f5565b8063912f309514610214578063a2bc7a1c14610246578063aff6274514610262578063b40ec02b14610293576100f5565b80634b6b9a8c116100d35780634b6b9a8c146101655780634e8bfabb1461019657806353df2b27146101b257806370eafd18146101e4576100f5565b806304e52369146100fa57806312862f7f1461011657806334eafb1114610147575b600080fd5b610114600480360381019061010f9190612b91565b610337565b005b610130600480360381019061012b9190612cef565b6109b1565b60405161013e929190612fd0565b60405180910390f35b61014f610d65565b60405161015c9190613020565b60405180910390f35b61017f600480360381019061017a9190613067565b610dd7565b60405161018d929190613198565b60405180910390f35b6101b060048036038101906101ab919061336b565b610fc8565b005b6101cc60048036038101906101c79190613412565b6114a5565b6040516101db93929190613627565b60405180910390f35b6101fe60048036038101906101f9919061366c565b611753565b60405161020b91906136c4565b60405180910390f35b61022e60048036038101906102299190613067565b611788565b60405161023d939291906136df565b60405180910390f35b610260600480360381019061025b919061366c565b611c4b565b005b61027c60048036038101906102779190612b91565b611e77565b60405161028a929190613782565b60405180910390f35b61029b6120e8565b6040516102a89190613020565b60405180910390f35b6102cb60048036038101906102c6919061366c565b6120f5565b6040516102d89190613020565b60405180910390f35b6102fb60048036038101906102f69190612b91565b61211f565b60405161030891906136c4565b60405180910390f35b610319612133565b005b610335600480360381019061033091906137b2565b6123ec565b005b6004826040516103479190613895565b908152602001604051809103902060009054906101000a900460ff166103a2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161039990613909565b60405180910390fd5b6103ac828261279b565b6103eb576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103e290613975565b60405180910390fd5b600060016002846040516103ff9190613895565b90815260200160405180910390208360405161041b91906139d1565b9081526020016040518091039020546104349190613a17565b90506000600160008560405161044a9190613895565b9081526020016040518091039020805490506104669190613a17565b905080821461085257600080856040516104809190613895565b908152602001604051809103902082815481106104a05761049f613a4b565b5b9060005260206000200180546104b590613aa9565b80601f01602080910402602001604051908101604052809291908181526020018280546104e190613aa9565b801561052e5780601f106105035761010080835404028352916020019161052e565b820191906000526020600020905b81548152906001019060200180831161051157829003601f168201915b5050505050905060006001866040516105479190613895565b9081526020016040518091039020838154811061056757610566613a4b565b5b906000526020600020906003020160405180606001604052908160008201805461059090613aa9565b80601f01602080910402602001604051908101604052809291908181526020018280546105bc90613aa9565b80156106095780601f106105de57610100808354040283529160200191610609565b820191906000526020600020905b8154815290600101906020018083116105ec57829003601f168201915b5050505050815260200160018201805461062290613aa9565b80601f016020809104026020016040519081016040528092919081815260200182805461064e90613aa9565b801561069b5780601f106106705761010080835404028352916020019161069b565b820191906000526020600020905b81548152906001019060200180831161067e57829003601f168201915b505050505081526020016002820180546106b490613aa9565b80601f01602080910402602001604051908101604052809291908181526020018280546106e090613aa9565b801561072d5780601f106107025761010080835404028352916020019161072d565b820191906000526020600020905b81548152906001019060200180831161071057829003601f168201915b5050505050815250509050816000876040516107499190613895565b9081526020016040518091039020858154811061076957610768613a4b565b5b90600052602060002001908161077f9190613c86565b50806001876040516107919190613895565b908152602001604051809103902085815481106107b1576107b0613a4b565b5b906000526020600020906003020160008201518160000190816107d49190613c86565b5060208201518160010190816107ea9190613c86565b5060408201518160020190816108009190613c86565b509050506001846108119190613d58565b6002876040516108219190613895565b90815260200160405180910390208360405161083d91906139d1565b90815260200160405180910390208190555050505b6000846040516108629190613895565b90815260200160405180910390208054806108805761087f613d8c565b5b60019003818190600052602060002001600061089c91906127e3565b90556001846040516108ae9190613895565b90815260200160405180910390208054806108cc576108cb613d8c565b5b6001900381819060005260206000209060030201600080820160006108f191906127e3565b60018201600061090191906127e3565b60028201600061091191906127e3565b505090556002846040516109259190613895565b90815260200160405180910390208360405161094191906139d1565b9081526020016040518091039020600090558260405161096191906139d1565b6040518091039020846040516109779190613895565b60405180910390207faf8967c7b21227d5d987c31cd064433b027cf5bd93330cdbe6b62909093c417260405160405180910390a350505050565b606080825167ffffffffffffffff8111156109cf576109ce6129c5565b5b604051908082528060200260200182016040528015610a0857816020015b6109f5612823565b8152602001906001900390816109ed5790505b509150825167ffffffffffffffff811115610a2657610a256129c5565b5b604051908082528060200260200182016040528015610a545781602001602082028036833780820191505090505b50905060005b8351811015610d5d57610a8785858381518110610a7a57610a79613a4b565b5b602002602001015161279b565b828281518110610a9a57610a99613a4b565b5b602002602001019015159081151581525050818181518110610abf57610abe613a4b565b5b602002602001015115610d505760006001600287604051610ae09190613895565b9081526020016040518091039020868481518110610b0157610b00613a4b565b5b6020026020010151604051610b1691906139d1565b908152602001604051809103902054610b2f9190613a17565b9050600186604051610b419190613895565b90815260200160405180910390208181548110610b6157610b60613a4b565b5b9060005260206000209060030201604051806060016040529081600082018054610b8a90613aa9565b80601f0160208091040260200160405190810160405280929190818152602001828054610bb690613aa9565b8015610c035780601f10610bd857610100808354040283529160200191610c03565b820191906000526020600020905b815481529060010190602001808311610be657829003601f168201915b50505050508152602001600182018054610c1c90613aa9565b80601f0160208091040260200160405190810160405280929190818152602001828054610c4890613aa9565b8015610c955780601f10610c6a57610100808354040283529160200191610c95565b820191906000526020600020905b815481529060010190602001808311610c7857829003601f168201915b50505050508152602001600282018054610cae90613aa9565b80601f0160208091040260200160405190810160405280929190818152602001828054610cda90613aa9565b8015610d275780601f10610cfc57610100808354040283529160200191610d27565b820191906000526020600020905b815481529060010190602001808311610d0a57829003601f168201915b505050505081525050848381518110610d4357610d42613a4b565b5b6020026020010181905250505b8080600101915050610a5a565b509250929050565b600080600090505b600380549050811015610dd357600060038281548110610d9057610d8f613a4b565b5b90600052602060002001604051610da79190613e53565b90815260200160405180910390208054905082610dc49190613d58565b91508080600101915050610d6d565b5090565b6060600080600086604051610dec9190613895565b9081526020016040518091039020905080805490509150818510610e6157600067ffffffffffffffff811115610e2557610e246129c5565b5b604051908082528060200260200182016040528015610e5857816020015b6060815260200190600190039081610e435790505b50925050610fc0565b60008583610e6f9190613a17565b90506000818611610e805785610e82565b815b90508067ffffffffffffffff811115610e9e57610e9d6129c5565b5b604051908082528060200260200182016040528015610ed157816020015b6060815260200190600190039081610ebc5790505b50945060005b81811015610fbb57838189610eec9190613d58565b81548110610efd57610efc613a4b565b5b906000526020600020018054610f1290613aa9565b80601f0160208091040260200160405190810160405280929190818152602001828054610f3e90613aa9565b8015610f8b5780601f10610f6057610100808354040283529160200191610f8b565b820191906000526020600020905b815481529060010190602001808311610f6e57829003601f168201915b5050505050868281518110610fa357610fa2613a4b565b5b60200260200101819052508080600101915050610ed7565b505050505b935093915050565b805182511461100c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161100390613edc565b60405180910390fd5b6000835111611050576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161104790613f48565b60405180910390fd5b6004836040516110609190613895565b908152602001604051809103902060009054906101000a900460ff166110ed576003839080600181540180825580915050600190039060005260206000200160009091909190915090816110b49190613fae565b5060016004846040516110c79190613895565b908152602001604051809103902060006101000a81548160ff0219169083151502179055505b60005b825181101561149f57600083828151811061110e5761110d613a4b565b5b60200260200101515111611157576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161114e906140cc565b60405180910390fd5b61117b8484838151811061116e5761116d613a4b565b5b602002602001015161279b565b61131b5760016000856040516111919190613895565b9081526020016040518091039020805490506111ad9190613d58565b6002856040516111bd9190613895565b90815260200160405180910390208483815181106111de576111dd613a4b565b5b60200260200101516040516111f391906139d1565b9081526020016040518091039020819055506000846040516112159190613895565b908152602001604051809103902083828151811061123657611235613a4b565b5b602002602001015190806001815401808255809150506001900390600052602060002001600090919091909150908161126f9190613c86565b506001846040516112809190613895565b90815260200160405180910390208282815181106112a1576112a0613a4b565b5b6020026020010151908060018154018082558091505060019003906000526020600020906003020160009091909190915060008201518160000190816112e79190613c86565b5060208201518160010190816112fd9190613c86565b5060408201518160020190816113139190613c86565b505050611420565b6000600160028660405161132f9190613895565b90815260200160405180910390208584815181106113505761134f613a4b565b5b602002602001015160405161136591906139d1565b90815260200160405180910390205461137e9190613a17565b905082828151811061139357611392613a4b565b5b60200260200101516001866040516113ab9190613895565b908152602001604051809103902082815481106113cb576113ca613a4b565b5b906000526020600020906003020160008201518160000190816113ee9190613c86565b5060208201518160010190816114049190613c86565b50604082015181600201908161141a9190613c86565b50905050505b82818151811061143357611432613a4b565b5b602002602001015160405161144891906139d1565b60405180910390208460405161145e9190613895565b60405180910390207fd00871f87cd1b1b4e50e5be511f060478c06a013856673c392f2adbfa65df8ad60405160405180910390a380806001019150506110f0565b50505050565b6060806000600380549050905080851061155b57600067ffffffffffffffff8111156114d4576114d36129c5565b5b60405190808252806020026020018201604052801561150757816020015b60608152602001906001900390816114f25790505b509250600067ffffffffffffffff811115611525576115246129c5565b5b6040519080825280602002602001820160405280156115535781602001602082028036833780820191505090505b50915061174c565b600085826115699190613a17565b9050600081861161157a578561157c565b815b90508067ffffffffffffffff811115611598576115976129c5565b5b6040519080825280602002602001820160405280156115cb57816020015b60608152602001906001900390816115b65790505b5094508067ffffffffffffffff8111156115e8576115e76129c5565b5b6040519080825280602002602001820160405280156116165781602001602082028036833780820191505090505b50935060005b818110156117485760006003828a6116349190613d58565b8154811061164557611644613a4b565b5b90600052602060002001805461165a90613aa9565b80601f016020809104026020016040519081016040528092919081815260200182805461168690613aa9565b80156116d35780601f106116a8576101008083540402835291602001916116d3565b820191906000526020600020905b8154815290600101906020018083116116b657829003601f168201915b50505050509050808783815181106116ee576116ed613a4b565b5b60200260200101819052506000816040516117099190613895565b90815260200160405180910390208054905086838151811061172e5761172d613a4b565b5b60200260200101818152505050808060010191505061161c565b5050505b9250925092565b60006004826040516117659190613895565b908152602001604051809103902060009054906101000a900460ff169050919050565b60608060008060008760405161179e9190613895565b908152602001604051809103902090508080549050915081861061186a57600067ffffffffffffffff8111156117d7576117d66129c5565b5b60405190808252806020026020018201604052801561180a57816020015b60608152602001906001900390816117f55790505b509350600067ffffffffffffffff811115611828576118276129c5565b5b60405190808252806020026020018201604052801561186157816020015b61184e612823565b8152602001906001900390816118465790505b50925050611c42565b600086836118789190613a17565b90506000818711611889578661188b565b815b90508067ffffffffffffffff8111156118a7576118a66129c5565b5b6040519080825280602002602001820160405280156118da57816020015b60608152602001906001900390816118c55790505b5095508067ffffffffffffffff8111156118f7576118f66129c5565b5b60405190808252806020026020018201604052801561193057816020015b61191d612823565b8152602001906001900390816119155790505b50945060005b81811015611c3d576000818a61194c9190613d58565b905084818154811061196157611960613a4b565b5b90600052602060002001805461197690613aa9565b80601f01602080910402602001604051908101604052809291908181526020018280546119a290613aa9565b80156119ef5780601f106119c4576101008083540402835291602001916119ef565b820191906000526020600020905b8154815290600101906020018083116119d257829003601f168201915b5050505050888381518110611a0757611a06613a4b565b5b602002602001018190525060018b604051611a229190613895565b90815260200160405180910390208181548110611a4257611a41613a4b565b5b9060005260206000209060030201604051806060016040529081600082018054611a6b90613aa9565b80601f0160208091040260200160405190810160405280929190818152602001828054611a9790613aa9565b8015611ae45780601f10611ab957610100808354040283529160200191611ae4565b820191906000526020600020905b815481529060010190602001808311611ac757829003601f168201915b50505050508152602001600182018054611afd90613aa9565b80601f0160208091040260200160405190810160405280929190818152602001828054611b2990613aa9565b8015611b765780601f10611b4b57610100808354040283529160200191611b76565b820191906000526020600020905b815481529060010190602001808311611b5957829003601f168201915b50505050508152602001600282018054611b8f90613aa9565b80601f0160208091040260200160405190810160405280929190818152602001828054611bbb90613aa9565b8015611c085780601f10611bdd57610100808354040283529160200191611c08565b820191906000526020600020905b815481529060010190602001808311611beb57829003601f168201915b505050505081525050878381518110611c2457611c23613a4b565b5b6020026020010181905250508080600101915050611936565b505050505b93509350939050565b600481604051611c5b9190613895565b908152602001604051809103902060009054906101000a900460ff16611cb6576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611cad90613909565b60405180910390fd5b60008082604051611cc79190613895565b9081526020016040518091039020905060005b8180549050811015611ddc576000828281548110611cfb57611cfa613a4b565b5b906000526020600020018054611d1090613aa9565b80601f0160208091040260200160405190810160405280929190818152602001828054611d3c90613aa9565b8015611d895780601f10611d5e57610100808354040283529160200191611d89565b820191906000526020600020905b815481529060010190602001808311611d6c57829003601f168201915b50505050509050600284604051611da09190613895565b908152602001604051809103902081604051611dbc91906139d1565b908152602001604051809103902060009055508080600101915050611cda565b50600082604051611ded9190613895565b90815260200160405180910390206000611e079190612844565b600182604051611e179190613895565b90815260200160405180910390206000611e319190612865565b81604051611e3f9190613895565b60405180910390207f372dd188f66e03080f62fc207ebf4954a98c81128ca2472aedfc273f0f7c788360405160405180910390a25050565b611e7f612823565b6000611e8b848461279b565b905080156120e15760006001600286604051611ea79190613895565b908152602001604051809103902085604051611ec391906139d1565b908152602001604051809103902054611edc9190613a17565b9050600185604051611eee9190613895565b90815260200160405180910390208181548110611f0e57611f0d613a4b565b5b9060005260206000209060030201604051806060016040529081600082018054611f3790613aa9565b80601f0160208091040260200160405190810160405280929190818152602001828054611f6390613aa9565b8015611fb05780601f10611f8557610100808354040283529160200191611fb0565b820191906000526020600020905b815481529060010190602001808311611f9357829003601f168201915b50505050508152602001600182018054611fc990613aa9565b80601f0160208091040260200160405190810160405280929190818152602001828054611ff590613aa9565b80156120425780601f1061201757610100808354040283529160200191612042565b820191906000526020600020905b81548152906001019060200180831161202557829003601f168201915b5050505050815260200160028201805461205b90613aa9565b80601f016020809104026020016040519081016040528092919081815260200182805461208790613aa9565b80156120d45780601f106120a9576101008083540402835291602001916120d4565b820191906000526020600020905b8154815290600101906020018083116120b757829003601f168201915b5050505050815250509250505b9250929050565b6000600380549050905090565b600080826040516121069190613895565b9081526020016040518091039020805490509050919050565b600061212b838361279b565b905092915050565b60005b6003805490508110156123af5760006003828154811061215957612158613a4b565b5b90600052602060002001805461216e90613aa9565b80601f016020809104026020016040519081016040528092919081815260200182805461219a90613aa9565b80156121e75780601f106121bc576101008083540402835291602001916121e7565b820191906000526020600020905b8154815290600101906020018083116121ca57829003601f168201915b50505050509050600080826040516121ff9190613895565b9081526020016040518091039020905060005b818054905081101561231457600082828154811061223357612232613a4b565b5b90600052602060002001805461224890613aa9565b80601f016020809104026020016040519081016040528092919081815260200182805461227490613aa9565b80156122c15780601f10612296576101008083540402835291602001916122c1565b820191906000526020600020905b8154815290600101906020018083116122a457829003601f168201915b505050505090506002846040516122d89190613895565b9081526020016040518091039020816040516122f491906139d1565b908152602001604051809103902060009055508080600101915050612212565b506000826040516123259190613895565b9081526020016040518091039020600061233f9190612844565b60018260405161234f9190613895565b908152602001604051809103902060006123699190612865565b600060048360405161237b9190613895565b908152602001604051809103902060006101000a81548160ff02191690831515021790555050508080600101915050612136565b50600360006123be9190612889565b7f30addec5e9e954699f286bae8e1558655b0d436c3d7b501014eb5c0b4a76e6db60405160405180910390a1565b6000835111612430576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161242790613f48565b60405180910390fd5b6000825111612474576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161246b906140cc565b60405180910390fd5b6004836040516124849190613895565b908152602001604051809103902060009054906101000a900460ff16612511576003839080600181540180825580915050600190039060005260206000200160009091909190915090816124d89190613fae565b5060016004846040516124eb9190613895565b908152602001604051809103902060006101000a81548160ff0219169083151502179055505b61251b838361279b565b61266d5760016000846040516125319190613895565b90815260200160405180910390208054905061254d9190613d58565b60028460405161255d9190613895565b90815260200160405180910390208360405161257991906139d1565b90815260200160405180910390208190555060008360405161259b9190613895565b9081526020016040518091039020829080600181540180825580915050600190039060005260206000200160009091909190915090816125db9190613c86565b506001836040516125ec9190613895565b908152602001604051809103902081908060018154018082558091505060019003906000526020600020906003020160009091909190915060008201518160000190816126399190613c86565b50602082015181600101908161264f9190613c86565b5060408201518160020190816126659190613c86565b50505061273e565b600060016002856040516126819190613895565b90815260200160405180910390208460405161269d91906139d1565b9081526020016040518091039020546126b69190613a17565b9050816001856040516126c99190613895565b908152602001604051809103902082815481106126e9576126e8613a4b565b5b9060005260206000209060030201600082015181600001908161270c9190613c86565b5060208201518160010190816127229190613c86565b5060408201518160020190816127389190613c86565b50905050505b8160405161274c91906139d1565b6040518091039020836040516127629190613895565b60405180910390207fd00871f87cd1b1b4e50e5be511f060478c06a013856673c392f2adbfa65df8ad60405160405180910390a3505050565b6000806002846040516127ae9190613895565b9081526020016040518091039020836040516127ca91906139d1565b9081526020016040518091039020541415905092915050565b5080546127ef90613aa9565b6000825580601f106128015750612820565b601f01602090049060005260206000209081019061281f91906128aa565b5b50565b60405180606001604052806060815260200160608152602001606081525090565b508054600082559060005260206000209081019061286291906128c7565b50565b508054600082556003029060005260206000209081019061288691906128eb565b50565b50805460008255906000526020600020908101906128a79190612932565b50565b5b808211156128c35760008160009055506001016128ab565b5090565b5b808211156128e757600081816128de91906127e3565b506001016128c8565b5090565b5b8082111561292e576000808201600061290591906127e3565b60018201600061291591906127e3565b60028201600061292591906127e3565b506003016128ec565b5090565b5b8082111561295257600081816129499190612956565b50600101612933565b5090565b50805461296290613aa9565b6000825580601f106129745750612993565b601f01602090049060005260206000209081019061299291906128aa565b5b50565b6000604051905090565b600080fd5b600080fd5b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6129fd826129b4565b810181811067ffffffffffffffff82111715612a1c57612a1b6129c5565b5b80604052505050565b6000612a2f612996565b9050612a3b82826129f4565b919050565b600067ffffffffffffffff821115612a5b57612a5a6129c5565b5b612a64826129b4565b9050602081019050919050565b82818337600083830152505050565b6000612a93612a8e84612a40565b612a25565b905082815260208101848484011115612aaf57612aae6129af565b5b612aba848285612a71565b509392505050565b600082601f830112612ad757612ad66129aa565b5b8135612ae7848260208601612a80565b91505092915050565b600067ffffffffffffffff821115612b0b57612b0a6129c5565b5b612b14826129b4565b9050602081019050919050565b6000612b34612b2f84612af0565b612a25565b905082815260208101848484011115612b5057612b4f6129af565b5b612b5b848285612a71565b509392505050565b600082601f830112612b7857612b776129aa565b5b8135612b88848260208601612b21565b91505092915050565b60008060408385031215612ba857612ba76129a0565b5b600083013567ffffffffffffffff811115612bc657612bc56129a5565b5b612bd285828601612ac2565b925050602083013567ffffffffffffffff811115612bf357612bf26129a5565b5b612bff85828601612b63565b9150509250929050565b600067ffffffffffffffff821115612c2457612c236129c5565b5b602082029050602081019050919050565b600080fd5b6000612c4d612c4884612c09565b612a25565b90508083825260208201905060208402830185811115612c7057612c6f612c35565b5b835b81811015612cb757803567ffffffffffffffff811115612c9557612c946129aa565b5b808601612ca28982612b63565b85526020850194505050602081019050612c72565b5050509392505050565b600082601f830112612cd657612cd56129aa565b5b8135612ce6848260208601612c3a565b91505092915050565b60008060408385031215612d0657612d056129a0565b5b600083013567ffffffffffffffff811115612d2457612d236129a5565b5b612d3085828601612ac2565b925050602083013567ffffffffffffffff811115612d5157612d506129a5565b5b612d5d85828601612cc1565b9150509250929050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b600081519050919050565b600082825260208201905092915050565b60005b83811015612dcd578082015181840152602081019050612db2565b60008484015250505050565b6000612de482612d93565b612dee8185612d9e565b9350612dfe818560208601612daf565b612e07816129b4565b840191505092915050565b60006060830160008301518482036000860152612e2f8282612dd9565b91505060208301518482036020860152612e498282612dd9565b91505060408301518482036040860152612e638282612dd9565b9150508091505092915050565b6000612e7c8383612e12565b905092915050565b6000602082019050919050565b6000612e9c82612d67565b612ea68185612d72565b935083602082028501612eb885612d83565b8060005b85811015612ef45784840389528151612ed58582612e70565b9450612ee083612e84565b925060208a01995050600181019050612ebc565b50829750879550505050505092915050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b60008115159050919050565b612f4781612f32565b82525050565b6000612f598383612f3e565b60208301905092915050565b6000602082019050919050565b6000612f7d82612f06565b612f878185612f11565b9350612f9283612f22565b8060005b83811015612fc3578151612faa8882612f4d565b9750612fb583612f65565b925050600181019050612f96565b5085935050505092915050565b60006040820190508181036000830152612fea8185612e91565b90508181036020830152612ffe8184612f72565b90509392505050565b6000819050919050565b61301a81613007565b82525050565b60006020820190506130356000830184613011565b92915050565b61304481613007565b811461304f57600080fd5b50565b6000813590506130618161303b565b92915050565b6000806000606084860312156130805761307f6129a0565b5b600084013567ffffffffffffffff81111561309e5761309d6129a5565b5b6130aa86828701612ac2565b93505060206130bb86828701613052565b92505060406130cc86828701613052565b9150509250925092565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b600061310e8383612dd9565b905092915050565b6000602082019050919050565b600061312e826130d6565b61313881856130e1565b93508360208202850161314a856130f2565b8060005b8581101561318657848403895281516131678582613102565b945061317283613116565b925060208a0199505060018101905061314e565b50829750879550505050505092915050565b600060408201905081810360008301526131b28185613123565b90506131c16020830184613011565b9392505050565b600067ffffffffffffffff8211156131e3576131e26129c5565b5b602082029050602081019050919050565b600080fd5b600080fd5b600060608284031215613214576132136131f4565b5b61321e6060612a25565b9050600082013567ffffffffffffffff81111561323e5761323d6131f9565b5b61324a84828501612b63565b600083015250602082013567ffffffffffffffff81111561326e5761326d6131f9565b5b61327a84828501612b63565b602083015250604082013567ffffffffffffffff81111561329e5761329d6131f9565b5b6132aa84828501612b63565b60408301525092915050565b60006132c96132c4846131c8565b612a25565b905080838252602082019050602084028301858111156132ec576132eb612c35565b5b835b8181101561333357803567ffffffffffffffff811115613311576133106129aa565b5b80860161331e89826131fe565b855260208501945050506020810190506132ee565b5050509392505050565b600082601f830112613352576133516129aa565b5b81356133628482602086016132b6565b91505092915050565b600080600060608486031215613384576133836129a0565b5b600084013567ffffffffffffffff8111156133a2576133a16129a5565b5b6133ae86828701612ac2565b935050602084013567ffffffffffffffff8111156133cf576133ce6129a5565b5b6133db86828701612cc1565b925050604084013567ffffffffffffffff8111156133fc576133fb6129a5565b5b6134088682870161333d565b9150509250925092565b60008060408385031215613429576134286129a0565b5b600061343785828601613052565b925050602061344885828601613052565b9150509250929050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b600081519050919050565b600082825260208201905092915050565b60006134a58261347e565b6134af8185613489565b93506134bf818560208601612daf565b6134c8816129b4565b840191505092915050565b60006134df838361349a565b905092915050565b6000602082019050919050565b60006134ff82613452565b613509818561345d565b93508360208202850161351b8561346e565b8060005b85811015613557578484038952815161353885826134d3565b9450613543836134e7565b925060208a0199505060018101905061351f565b50829750879550505050505092915050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b61359e81613007565b82525050565b60006135b08383613595565b60208301905092915050565b6000602082019050919050565b60006135d482613569565b6135de8185613574565b93506135e983613585565b8060005b8381101561361a57815161360188826135a4565b975061360c836135bc565b9250506001810190506135ed565b5085935050505092915050565b6000606082019050818103600083015261364181866134f4565b9050818103602083015261365581856135c9565b90506136646040830184613011565b949350505050565b600060208284031215613682576136816129a0565b5b600082013567ffffffffffffffff8111156136a05761369f6129a5565b5b6136ac84828501612ac2565b91505092915050565b6136be81612f32565b82525050565b60006020820190506136d960008301846136b5565b92915050565b600060608201905081810360008301526136f98186613123565b9050818103602083015261370d8185612e91565b905061371c6040830184613011565b949350505050565b600060608301600083015184820360008601526137418282612dd9565b9150506020830151848203602086015261375b8282612dd9565b915050604083015184820360408601526137758282612dd9565b9150508091505092915050565b6000604082019050818103600083015261379c8185613724565b90506137ab60208301846136b5565b9392505050565b6000806000606084860312156137cb576137ca6129a0565b5b600084013567ffffffffffffffff8111156137e9576137e86129a5565b5b6137f586828701612ac2565b935050602084013567ffffffffffffffff811115613816576138156129a5565b5b61382286828701612b63565b925050604084013567ffffffffffffffff811115613843576138426129a5565b5b61384f868287016131fe565b9150509250925092565b600081905092915050565b600061386f8261347e565b6138798185613859565b9350613889818560208601612daf565b80840191505092915050565b60006138a18284613864565b915081905092915050565b600082825260208201905092915050565b7f4e616d65737061636520646f6573206e6f742065786973740000000000000000600082015250565b60006138f36018836138ac565b91506138fe826138bd565b602082019050919050565b60006020820190508181036000830152613922816138e6565b9050919050565b7f4b657920646f6573206e6f7420657869737420696e206e616d65737061636500600082015250565b600061395f601f836138ac565b915061396a82613929565b602082019050919050565b6000602082019050818103600083015261398e81613952565b9050919050565b600081905092915050565b60006139ab82612d93565b6139b58185613995565b93506139c5818560208601612daf565b80840191505092915050565b60006139dd82846139a0565b915081905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000613a2282613007565b9150613a2d83613007565b9250828203905081811115613a4557613a446139e8565b5b92915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b60006002820490506001821680613ac157607f821691505b602082108103613ad457613ad3613a7a565b5b50919050565b60008190508160005260206000209050919050565b60006020601f8301049050919050565b600082821b905092915050565b600060088302613b3c7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82613aff565b613b468683613aff565b95508019841693508086168417925050509392505050565b6000819050919050565b6000613b83613b7e613b7984613007565b613b5e565b613007565b9050919050565b6000819050919050565b613b9d83613b68565b613bb1613ba982613b8a565b848454613b0c565b825550505050565b600090565b613bc6613bb9565b613bd1818484613b94565b505050565b5b81811015613bf557613bea600082613bbe565b600181019050613bd7565b5050565b601f821115613c3a57613c0b81613ada565b613c1484613aef565b81016020851015613c23578190505b613c37613c2f85613aef565b830182613bd6565b50505b505050565b600082821c905092915050565b6000613c5d60001984600802613c3f565b1980831691505092915050565b6000613c768383613c4c565b9150826002028217905092915050565b613c8f82612d93565b67ffffffffffffffff811115613ca857613ca76129c5565b5b613cb28254613aa9565b613cbd828285613bf9565b600060209050601f831160018114613cf05760008415613cde578287015190505b613ce88582613c6a565b865550613d50565b601f198416613cfe86613ada565b60005b82811015613d2657848901518255600182019150602085019450602081019050613d01565b86831015613d435784890151613d3f601f891682613c4c565b8355505b6001600288020188555050505b505050505050565b6000613d6382613007565b9150613d6e83613007565b9250828201905080821115613d8657613d856139e8565b5b92915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b60008190508160005260206000209050919050565b60008154613ddd81613aa9565b613de78186613859565b94506001821660008114613e025760018114613e1757613e4a565b60ff1983168652811515820286019350613e4a565b613e2085613dbb565b60005b83811015613e4257815481890152600182019150602081019050613e23565b838801955050505b50505092915050565b6000613e5f8284613dd0565b915081905092915050565b7f4b65797320616e642076616c75657320617272617973206d757374206861766560008201527f2073616d65206c656e6774680000000000000000000000000000000000000000602082015250565b6000613ec6602c836138ac565b9150613ed182613e6a565b604082019050919050565b60006020820190508181036000830152613ef581613eb9565b9050919050565b7f4e616d6573706163652063616e6e6f7420626520656d70747900000000000000600082015250565b6000613f326019836138ac565b9150613f3d82613efc565b602082019050919050565b60006020820190508181036000830152613f6181613f25565b9050919050565b601f821115613fa957613f7a81613dbb565b613f8384613aef565b81016020851015613f92578190505b613fa6613f9e85613aef565b830182613bd6565b50505b505050565b613fb78261347e565b67ffffffffffffffff811115613fd057613fcf6129c5565b5b613fda8254613aa9565b613fe5828285613f68565b600060209050601f8311600181146140185760008415614006578287015190505b6140108582613c6a565b865550614078565b601f19841661402686613dbb565b60005b8281101561404e57848901518255600182019150602085019450602081019050614029565b8683101561406b5784890151614067601f891682613c4c565b8355505b6001600288020188555050505b505050505050565b7f4b65792063616e6e6f7420626520656d70747900000000000000000000000000600082015250565b60006140b66013836138ac565b91506140c182614080565b602082019050919050565b600060208201905081810360008301526140e5816140a9565b905091905056fea26469706673582212202ff7da17132a43f690d61f599721b55cc44e8324d1af1c4c5ca8ce4a4fe52e7664736f6c63430008180033" From e769614f840422560678b79b893b1ed5e8591265 Mon Sep 17 00:00:00 2001 From: envestcc Date: Fri, 22 Aug 2025 18:07:44 +0800 Subject: [PATCH 08/26] address comment --- state/contract_storage.go | 3 +++ state/contract_storage_namespaced.go | 10 +++++----- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/state/contract_storage.go b/state/contract_storage.go index 889e95c74e..3f190e4684 100644 --- a/state/contract_storage.go +++ b/state/contract_storage.go @@ -6,6 +6,7 @@ import ( "github.com/iotexproject/iotex-core/v2/systemcontracts" ) +// ContractStorage defines the interface for contract storage operations type ContractStorage interface { StoreToContract(ns string, key []byte, backend systemcontracts.ContractBackend) error LoadFromContract(ns string, key []byte, backend systemcontracts.ContractBackend) error @@ -14,6 +15,7 @@ type ContractStorage interface { BatchFromContract(ns string, keys [][]byte, backend systemcontracts.ContractBackend) ([]any, error) } +// ContractStorageStandard defines the interface for standard contract storage operations type ContractStorageStandard interface { ContractStorageAddress(ns string, key []byte) (address.Address, error) New() ContractStorageStandard @@ -21,6 +23,7 @@ type ContractStorageStandard interface { Deserialize([]byte) error } +// ContractStorageProxy defines the interface for contract storage proxy operations type ContractStorageProxy interface { ContractStorageProxy() ContractStorage } diff --git a/state/contract_storage_namespaced.go b/state/contract_storage_namespaced.go index f244dc0390..69b0e2a067 100644 --- a/state/contract_storage_namespaced.go +++ b/state/contract_storage_namespaced.go @@ -31,7 +31,7 @@ func (cs *contractStorageNamespacedWrapper) StoreToContract(ns string, key []byt if err := contract.Put(ns, key, systemcontracts.NamespaceGenericValue{PrimaryData: data}); err != nil { return errors.Wrapf(err, "failed to store storage standard to contract %s", contract.Address().Hex()) } - log.S().Infof("Stored storage standard to contract %s with key %x, value: %+v", contract.Address().Hex(), key, cs.standard) + log.S().Debugf("Stored storage standard to contract %s with key %x, value: %+v", contract.Address().Hex(), key, cs.standard) return nil } @@ -50,7 +50,7 @@ func (cs *contractStorageNamespacedWrapper) LoadFromContract(ns string, key []by if err := cs.standard.Deserialize(value.Value.PrimaryData); err != nil { return errors.Wrap(err, "failed to deserialize storage standard") } - log.S().Infof("Loaded storage standard from contract %s with key %x, value: %+v", contract.Address().Hex(), key, cs.standard) + log.S().Debugf("Loaded storage standard from contract %s with key %x, value: %+v", contract.Address().Hex(), key, cs.standard) return nil } @@ -62,7 +62,7 @@ func (cs *contractStorageNamespacedWrapper) DeleteFromContract(ns string, key [] if err := contract.Remove(ns, key); err != nil { return errors.Wrapf(err, "failed to delete storage standard from contract %s with key %x", contract.Address().Hex(), key) } - log.S().Infof("Deleted storage standard from contract %s with key %x", contract.Address().Hex(), key) + log.S().Debugf("Deleted storage standard from contract %s with key %x", contract.Address().Hex(), key) return nil } @@ -82,7 +82,7 @@ func (cs *contractStorageNamespacedWrapper) ListFromContract(ns string, backend if err != nil { return nil, nil, errors.Wrapf(err, "failed to list storage standards from contract %s", contract.Address().Hex()) } - log.S().Infof("Listed storage standards from contract %s with keys %v", contract.Address().Hex(), listResult.KeyList) + log.S().Debugf("Listed storage standards from contract %s with keys %v", contract.Address().Hex(), listResult.KeyList) var indices []any for _, value := range listResult.Values { bi := cs.standard.New() @@ -116,7 +116,7 @@ func (cs *contractStorageNamespacedWrapper) BatchFromContract(ns string, keys [] } results = append(results, res) } - log.S().Infof("Batch loaded %d storage standard from contract %s with keys %d", len(results), contract.Address().Hex(), len(keys)) + log.S().Debugf("Batch loaded %d storage standard from contract %s with keys %d", len(results), contract.Address().Hex(), len(keys)) return results, nil } From 383070536d061248a7a41c883f1d73b4e015bba1 Mon Sep 17 00:00:00 2001 From: envestcc Date: Mon, 25 Aug 2025 08:51:40 +0800 Subject: [PATCH 09/26] address comment --- systemcontracts/GenericStorage.sol | 18 ++++++---------- systemcontracts/NamespaceStorage.sol | 32 ++++++++++------------------ 2 files changed, 17 insertions(+), 33 deletions(-) diff --git a/systemcontracts/GenericStorage.sol b/systemcontracts/GenericStorage.sol index e40f7b3090..1e39583b8f 100644 --- a/systemcontracts/GenericStorage.sol +++ b/systemcontracts/GenericStorage.sol @@ -67,8 +67,7 @@ contract GenericStorage { values_.push(value); // Add corresponding value to values array } else { // Update existing value - uint256 index = keyIndex_[key] - 1; - values_[index] = value; + values_[keyIndex_[key] - 1] = value; } emit DataStored(key); @@ -87,12 +86,9 @@ contract GenericStorage { // If it's not the last element, move the last element to the removed position if (indexToRemove != lastIndex) { - bytes memory lastKey = keys_[lastIndex]; - GenericValue memory lastValue = values_[lastIndex]; - - keys_[indexToRemove] = lastKey; - values_[indexToRemove] = lastValue; // Move the corresponding value - keyIndex_[lastKey] = indexToRemove + 1; // Update the moved key's index (add 1) + keys_[indexToRemove] = keys_[lastIndex]; + values_[indexToRemove] = values_[lastIndex]; + keyIndex_[keys_[lastIndex]] = indexToRemove + 1; // Update the moved key's index (add 1) } // Remove the last elements from both arrays @@ -112,8 +108,7 @@ contract GenericStorage { function get(bytes memory key) external view returns (GenericValue memory value, bool keyExists) { keyExists = _keyExists(key); if (keyExists) { - uint256 index = keyIndex_[key] - 1; - value = values_[index]; // Get value from values array + value = values_[keyIndex_[key] - 1]; // Get value from values array } return (value, keyExists); } @@ -134,8 +129,7 @@ contract GenericStorage { for (uint256 i = 0; i < keyList.length; i++) { existsFlags[i] = _keyExists(keyList[i]); if (existsFlags[i]) { - uint256 index = keyIndex_[keyList[i]] - 1; - values[i] = values_[index]; // Get value from values array + values[i] = values_[keyIndex_[keyList[i]] - 1]; // Get value from values array } } diff --git a/systemcontracts/NamespaceStorage.sol b/systemcontracts/NamespaceStorage.sol index f5590b3383..cfc8c767a1 100644 --- a/systemcontracts/NamespaceStorage.sol +++ b/systemcontracts/NamespaceStorage.sol @@ -76,8 +76,7 @@ contract NamespaceStorage { namespaceValues_[namespace].push(value); } else { // Update existing value - uint256 index = keyIndex_[namespace][key] - 1; - namespaceValues_[namespace][index] = value; + namespaceValues_[namespace][keyIndex_[namespace][key] - 1] = value; } emit DataStored(namespace, key); @@ -96,8 +95,7 @@ contract NamespaceStorage { ) { keyExists = _keyExists(namespace, key); if (keyExists) { - uint256 index = keyIndex_[namespace][key] - 1; - value = namespaceValues_[namespace][index]; + value = namespaceValues_[namespace][keyIndex_[namespace][key] - 1]; } return (value, keyExists); } @@ -117,12 +115,9 @@ contract NamespaceStorage { // If it's not the last element, move the last element to the removed position if (indexToRemove != lastIndex) { - bytes memory lastKey = namespaceKeys_[namespace][lastIndex]; - GenericValue memory lastValue = namespaceValues_[namespace][lastIndex]; - - namespaceKeys_[namespace][indexToRemove] = lastKey; - namespaceValues_[namespace][indexToRemove] = lastValue; - keyIndex_[namespace][lastKey] = indexToRemove + 1; // Update the moved key's index (add 1) + namespaceKeys_[namespace][indexToRemove] = namespaceKeys_[namespace][lastIndex]; + namespaceValues_[namespace][indexToRemove] = namespaceValues_[namespace][lastIndex]; + keyIndex_[namespace][namespaceKeys_[namespace][lastIndex]] = indexToRemove + 1; // Update the moved key's index (add 1) } // Remove the last elements from both arrays @@ -150,8 +145,7 @@ contract NamespaceStorage { for (uint256 i = 0; i < keyList.length; i++) { existsFlags[i] = _keyExists(namespace, keyList[i]); if (existsFlags[i]) { - uint256 index = keyIndex_[namespace][keyList[i]] - 1; - values[i] = namespaceValues_[namespace][index]; + values[i] = namespaceValues_[namespace][keyIndex_[namespace][keyList[i]] - 1]; } } @@ -188,8 +182,7 @@ contract NamespaceStorage { namespaceValues_[namespace].push(values[i]); } else { // Update existing value - uint256 index = keyIndex_[namespace][keys[i]] - 1; - namespaceValues_[namespace][index] = values[i]; + namespaceValues_[namespace][keyIndex_[namespace][keys[i]] - 1] = values[i]; } emit DataStored(namespace, keys[i]); @@ -298,9 +291,8 @@ contract NamespaceStorage { counts = new uint256[](actualLimit); for (uint256 i = 0; i < actualLimit; i++) { - string memory ns = namespaces_[offset + i]; - namespaceList[i] = ns; - counts[i] = namespaceKeys_[ns].length; + namespaceList[i] = namespaces_[offset + i]; + counts[i] = namespaceKeys_[namespaces_[offset + i]].length; } return (namespaceList, counts, total); @@ -364,8 +356,7 @@ contract NamespaceStorage { // Clear all key indices in the namespace for (uint256 i = 0; i < keys.length; i++) { - bytes memory key = keys[i]; - delete keyIndex_[namespace][key]; + delete keyIndex_[namespace][keys[i]]; } // Clear both arrays for the namespace @@ -387,8 +378,7 @@ contract NamespaceStorage { // Clear all key indices in this namespace for (uint256 j = 0; j < keys.length; j++) { - bytes memory key = keys[j]; - delete keyIndex_[namespace][key]; + delete keyIndex_[namespace][keys[j]]; } // Clear both arrays for this namespace From 4931c1926b71d443bdf556f631efc4235ee2afe9 Mon Sep 17 00:00:00 2001 From: envestcc Date: Mon, 1 Sep 2025 06:48:18 +0800 Subject: [PATCH 10/26] fix lock --- state/factory/workingsetstore.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/state/factory/workingsetstore.go b/state/factory/workingsetstore.go index ce136f9212..e1c460d936 100644 --- a/state/factory/workingsetstore.go +++ b/state/factory/workingsetstore.go @@ -88,8 +88,6 @@ func (store *stateDBWorkingSetStore) Put(ns string, key []byte, value []byte) er } func (store *stateDBWorkingSetStore) putKV(ns string, key []byte, value []byte) error { - store.lock.Lock() - defer store.lock.Unlock() if err := store.flusher.KVStoreWithBuffer().Put(ns, key, value); err != nil { return errors.Wrap(err, "failed to put value") } From 791c488ae0d13e1f86806e68ddb4b55a0b927d67 Mon Sep 17 00:00:00 2001 From: envestcc Date: Mon, 1 Sep 2025 07:13:47 +0800 Subject: [PATCH 11/26] fix test --- state/factory/workingsetstore_test.go | 31 ++++++++++++++++++--------- 1 file changed, 21 insertions(+), 10 deletions(-) diff --git a/state/factory/workingsetstore_test.go b/state/factory/workingsetstore_test.go index c10ec3de4f..a4504223e5 100644 --- a/state/factory/workingsetstore_test.go +++ b/state/factory/workingsetstore_test.go @@ -19,6 +19,17 @@ import ( "github.com/iotexproject/iotex-core/v2/pkg/util/byteutil" ) +type valueBytes []byte + +func (v *valueBytes) Serialize() ([]byte, error) { + return *v, nil +} + +func (v *valueBytes) Deserialize(data []byte) error { + *v = data + return nil +} + func TestStateDBWorkingSetStore(t *testing.T) { require := require.New(t) ctx := context.Background() @@ -30,28 +41,28 @@ func TestStateDBWorkingSetStore(t *testing.T) { require.NoError(store.Start(ctx)) namespace := "namespace" key1 := []byte("key1") - value1 := []byte("value1") + value1 := valueBytes("value1") key2 := []byte("key2") - value2 := []byte("value2") + value2 := valueBytes("value2") key3 := []byte("key3") - value3 := []byte("value3") + value3 := valueBytes("value3") t.Run("test kvstore feature", func(t *testing.T) { - var value []byte + var value valueBytes err := store.GetObject(namespace, key1, &value) require.Error(err) require.NoError(store.DeleteObject(namespace, key1, &value)) - require.NoError(store.PutObject(namespace, key1, value1)) - var valueInStore []byte + require.NoError(store.PutObject(namespace, key1, &value1)) + var valueInStore valueBytes err = store.GetObject(namespace, key1, &valueInStore) require.NoError(err) require.True(bytes.Equal(value1, valueInStore)) sn1 := store.Snapshot() - require.NoError(store.PutObject(namespace, key2, value2)) + require.NoError(store.PutObject(namespace, key2, &value2)) err = store.GetObject(namespace, key2, &valueInStore) require.NoError(err) require.True(bytes.Equal(value2, valueInStore)) store.Snapshot() - require.NoError(store.PutObject(namespace, key3, value3)) + require.NoError(store.PutObject(namespace, key3, &value3)) err = store.GetObject(namespace, key3, &valueInStore) require.NoError(err) require.True(bytes.Equal(value3, valueInStore)) @@ -84,7 +95,7 @@ func TestStateDBWorkingSetStore(t *testing.T) { t.Run("finalize & commit", func(t *testing.T) { height := uint64(100) ctx := context.Background() - var value []byte + var value valueBytes err := store.GetObject(AccountKVNamespace, []byte(CurrentHeightKey), &value) require.Error(err) _, err = inMemStore.Get(AccountKVNamespace, []byte(CurrentHeightKey)) @@ -93,7 +104,7 @@ func TestStateDBWorkingSetStore(t *testing.T) { BlockHeight: height, }) require.NoError(store.Finalize(ctx)) - var heightInStore []byte + var heightInStore valueBytes err = store.GetObject(AccountKVNamespace, []byte(CurrentHeightKey), &heightInStore) require.NoError(err) require.True(bytes.Equal(heightInStore, byteutil.Uint64ToBytes(height))) From ebb0d13bc92ea00216b1b4458f6b3755815ee277 Mon Sep 17 00:00:00 2001 From: envestcc Date: Thu, 11 Sep 2025 11:48:48 +0800 Subject: [PATCH 12/26] refactor: together erigon store --- .../{ => erigonstore}/contract_backend.go | 2 +- .../erigonstore}/contract_storage.go | 2 +- .../contract_storage_namespaced.go | 5 +- .../erigonstore}/contract_storage_standard.go | 5 +- .../workingsetstore_erigon.go | 110 +++++++++--------- state/factory/statedb.go | 11 +- state/factory/workingset.go | 7 +- .../workingsetstore_erigon_simulate.go | 11 +- 8 files changed, 82 insertions(+), 71 deletions(-) rename state/factory/{ => erigonstore}/contract_backend.go (99%) rename state/{ => factory/erigonstore}/contract_storage.go (98%) rename state/{ => factory/erigonstore}/contract_storage_namespaced.go (96%) rename state/{ => factory/erigonstore}/contract_storage_standard.go (95%) rename state/factory/{ => erigonstore}/workingsetstore_erigon.go (82%) diff --git a/state/factory/contract_backend.go b/state/factory/erigonstore/contract_backend.go similarity index 99% rename from state/factory/contract_backend.go rename to state/factory/erigonstore/contract_backend.go index a6ce741daf..29a9a9d3c9 100644 --- a/state/factory/contract_backend.go +++ b/state/factory/erigonstore/contract_backend.go @@ -1,4 +1,4 @@ -package factory +package erigonstore import ( "context" diff --git a/state/contract_storage.go b/state/factory/erigonstore/contract_storage.go similarity index 98% rename from state/contract_storage.go rename to state/factory/erigonstore/contract_storage.go index 3f190e4684..7ec3679c12 100644 --- a/state/contract_storage.go +++ b/state/factory/erigonstore/contract_storage.go @@ -1,4 +1,4 @@ -package state +package erigonstore import ( "github.com/iotexproject/iotex-address/address" diff --git a/state/contract_storage_namespaced.go b/state/factory/erigonstore/contract_storage_namespaced.go similarity index 96% rename from state/contract_storage_namespaced.go rename to state/factory/erigonstore/contract_storage_namespaced.go index 69b0e2a067..2c185ac153 100644 --- a/state/contract_storage_namespaced.go +++ b/state/factory/erigonstore/contract_storage_namespaced.go @@ -1,4 +1,4 @@ -package state +package erigonstore import ( "math/big" @@ -7,6 +7,7 @@ import ( "github.com/pkg/errors" "github.com/iotexproject/iotex-core/v2/pkg/log" + "github.com/iotexproject/iotex-core/v2/state" "github.com/iotexproject/iotex-core/v2/systemcontracts" ) @@ -45,7 +46,7 @@ func (cs *contractStorageNamespacedWrapper) LoadFromContract(ns string, key []by return errors.Wrapf(err, "failed to get storage standard from contract %s with key %x", contract.Address().Hex(), key) } if !value.KeyExists { - return errors.Wrapf(ErrStateNotExist, "storage standard does not exist in contract %s with key %x", contract.Address().Hex(), key) + return errors.Wrapf(state.ErrStateNotExist, "storage standard does not exist in contract %s with key %x", contract.Address().Hex(), key) } if err := cs.standard.Deserialize(value.Value.PrimaryData); err != nil { return errors.Wrap(err, "failed to deserialize storage standard") diff --git a/state/contract_storage_standard.go b/state/factory/erigonstore/contract_storage_standard.go similarity index 95% rename from state/contract_storage_standard.go rename to state/factory/erigonstore/contract_storage_standard.go index b2037b32a0..16d5ac722a 100644 --- a/state/contract_storage_standard.go +++ b/state/factory/erigonstore/contract_storage_standard.go @@ -1,10 +1,11 @@ -package state +package erigonstore import ( "github.com/ethereum/go-ethereum/common" "github.com/pkg/errors" "github.com/iotexproject/iotex-core/v2/pkg/log" + "github.com/iotexproject/iotex-core/v2/state" "github.com/iotexproject/iotex-core/v2/systemcontracts" ) @@ -41,7 +42,7 @@ func (cs *contractStorageStandardWrapper) LoadFromContract(ns string, key []byte return errors.Wrapf(err, "failed to get storage standard from contract %s with key %x", contract.Address().Hex(), key) } if !value.KeyExists { - return errors.Wrapf(ErrStateNotExist, "storage standard does not exist in contract %s with key %x", contract.Address().Hex(), key) + return errors.Wrapf(state.ErrStateNotExist, "storage standard does not exist in contract %s with key %x", contract.Address().Hex(), key) } if err := cs.standard.Deserialize(value.Value.PrimaryData); err != nil { return errors.Wrap(err, "failed to deserialize storage standard") diff --git a/state/factory/workingsetstore_erigon.go b/state/factory/erigonstore/workingsetstore_erigon.go similarity index 82% rename from state/factory/workingsetstore_erigon.go rename to state/factory/erigonstore/workingsetstore_erigon.go index 2c6b4af7c1..fce6f60825 100644 --- a/state/factory/workingsetstore_erigon.go +++ b/state/factory/erigonstore/workingsetstore_erigon.go @@ -1,4 +1,4 @@ -package factory +package erigonstore import ( "context" @@ -42,24 +42,24 @@ var ( heightKey = []byte("height") ) -type erigonDB struct { +type ErigonDB struct { path string rw kv.RwDB } -type erigonWorkingSetStore struct { - db *erigonDB +type ErigonWorkingSetStore struct { + db *ErigonDB intraBlockState *erigonstate.IntraBlockState tx kv.Tx sr erigonstate.StateReader ctx context.Context } -func newErigonDB(path string) *erigonDB { - return &erigonDB{path: path} +func NewErigonDB(path string) *ErigonDB { + return &ErigonDB{path: path} } -func (db *erigonDB) Start(ctx context.Context) error { +func (db *ErigonDB) Start(ctx context.Context) error { log.L().Info("starting history state index") lg := erigonlog.New() lg.SetHandler(erigonlog.StdoutHandler) @@ -74,20 +74,20 @@ func (db *erigonDB) Start(ctx context.Context) error { return nil } -func (db *erigonDB) Stop(ctx context.Context) { +func (db *ErigonDB) Stop(ctx context.Context) { if db.rw != nil { db.rw.Close() } } -func (db *erigonDB) newErigonStore(ctx context.Context, height uint64) (*erigonWorkingSetStore, error) { +func (db *ErigonDB) NewErigonStore(ctx context.Context, height uint64) (*ErigonWorkingSetStore, error) { tx, err := db.rw.BeginRo(ctx) if err != nil { return nil, err } r := erigonstate.NewPlainStateReader(tx) intraBlockState := erigonstate.New(r) - return &erigonWorkingSetStore{ + return &ErigonWorkingSetStore{ db: db, tx: tx, intraBlockState: intraBlockState, @@ -96,14 +96,14 @@ func (db *erigonDB) newErigonStore(ctx context.Context, height uint64) (*erigonW }, nil } -func (db *erigonDB) newErigonStoreDryrun(ctx context.Context, height uint64) (*erigonWorkingSetStore, error) { +func (db *ErigonDB) NewErigonStoreDryrun(ctx context.Context, height uint64) (*ErigonWorkingSetStore, error) { tx, err := db.rw.BeginRo(ctx) if err != nil { return nil, err } tsw := erigonstate.NewPlainState(tx, height, nil) intraBlockState := erigonstate.New(tsw) - return &erigonWorkingSetStore{ + return &ErigonWorkingSetStore{ db: db, tx: tx, intraBlockState: intraBlockState, @@ -112,7 +112,7 @@ func (db *erigonDB) newErigonStoreDryrun(ctx context.Context, height uint64) (*e }, nil } -func (db *erigonDB) BatchPrune(ctx context.Context, from, to, batch uint64) error { +func (db *ErigonDB) BatchPrune(ctx context.Context, from, to, batch uint64) error { if from >= to { return errors.Errorf("invalid prune range: from %d >= to %d", from, to) } @@ -148,7 +148,7 @@ func (db *erigonDB) BatchPrune(ctx context.Context, from, to, batch uint64) erro return db.Prune(ctx, nil, from, to) } -func (db *erigonDB) Prune(ctx context.Context, tx kv.RwTx, from, to uint64) error { +func (db *ErigonDB) Prune(ctx context.Context, tx kv.RwTx, from, to uint64) error { if from >= to { return errors.Errorf("invalid prune range: from %d >= to %d", from, to) } @@ -180,15 +180,15 @@ func (db *erigonDB) Prune(ctx context.Context, tx kv.RwTx, from, to uint64) erro return nil } -func (store *erigonWorkingSetStore) Start(ctx context.Context) error { +func (store *ErigonWorkingSetStore) Start(ctx context.Context) error { return nil } -func (store *erigonWorkingSetStore) Stop(ctx context.Context) error { +func (store *ErigonWorkingSetStore) Stop(ctx context.Context) error { return nil } -func (store *erigonWorkingSetStore) FinalizeTx(ctx context.Context) error { +func (store *ErigonWorkingSetStore) FinalizeTx(ctx context.Context) error { blkCtx := protocol.MustGetBlockCtx(ctx) g := genesis.MustExtractGenesisContext(ctx) chainCfg, err := evm.NewChainConfig(ctx) @@ -200,11 +200,11 @@ func (store *erigonWorkingSetStore) FinalizeTx(ctx context.Context) error { return store.intraBlockState.FinalizeTx(rules, erigonstate.NewNoopWriter()) } -func (store *erigonWorkingSetStore) Finalize(ctx context.Context) error { +func (store *ErigonWorkingSetStore) Finalize(ctx context.Context) error { return nil } -func (store *erigonWorkingSetStore) prepareCommit(ctx context.Context, tx kv.RwTx, retention uint64) error { +func (store *ErigonWorkingSetStore) prepareCommit(ctx context.Context, tx kv.RwTx, retention uint64) error { blkCtx := protocol.MustGetBlockCtx(ctx) height := blkCtx.BlockHeight ts := blkCtx.BlockTimeStamp.Unix() @@ -247,7 +247,7 @@ func (store *erigonWorkingSetStore) prepareCommit(ctx context.Context, tx kv.RwT return store.db.Prune(ctx, tx, from, to) } -func (store *erigonWorkingSetStore) Commit(ctx context.Context, retention uint64) error { +func (store *ErigonWorkingSetStore) Commit(ctx context.Context, retention uint64) error { defer store.tx.Rollback() // BeginRw accounting for the context Done signal // statedb has been committed, so we should not use the context @@ -266,23 +266,23 @@ func (store *erigonWorkingSetStore) Commit(ctx context.Context, retention uint64 return nil } -func (store *erigonWorkingSetStore) Close() { +func (store *ErigonWorkingSetStore) Close() { store.tx.Rollback() } -func (store *erigonWorkingSetStore) Snapshot() int { +func (store *ErigonWorkingSetStore) Snapshot() int { return store.intraBlockState.Snapshot() } -func (store *erigonWorkingSetStore) RevertSnapshot(sn int) error { +func (store *ErigonWorkingSetStore) RevertSnapshot(sn int) error { store.intraBlockState.RevertToSnapshot(sn) return nil } -func (store *erigonWorkingSetStore) ResetSnapshots() {} +func (store *ErigonWorkingSetStore) ResetSnapshots() {} -func (store *erigonWorkingSetStore) PutObject(ns string, key []byte, obj any) (err error) { - storage := store.objectContractStorage(obj) +func (store *ErigonWorkingSetStore) PutObject(ns string, key []byte, obj any) (err error) { + storage := ObjectContractStorage(obj) if storage != nil { log.L().Debug("put object", zap.String("namespace", ns), log.Hex("key", key), zap.String("type", fmt.Sprintf("%T", obj)), zap.Any("content", obj)) return storage.StoreToContract(ns, key, store.newContractBackend(store.ctx, store.intraBlockState, store.sr)) @@ -294,10 +294,10 @@ func (store *erigonWorkingSetStore) PutObject(ns string, key []byte, obj any) (e return store.Put(ns, key, value) } -func (store *erigonWorkingSetStore) Put(ns string, key []byte, value []byte) (err error) { +func (store *ErigonWorkingSetStore) Put(ns string, key []byte, value []byte) (err error) { // only handling account, contract storage handled by evm adapter // others are ignored - if ns != AccountKVNamespace { + if ns != state.AccountKVNamespace { return nil } defer func() { @@ -321,8 +321,8 @@ func (store *erigonWorkingSetStore) Put(ns string, key []byte, value []byte) (er return nil } -func (store *erigonWorkingSetStore) GetObject(ns string, key []byte, obj any) error { - storage := store.objectContractStorage(obj) +func (store *ErigonWorkingSetStore) GetObject(ns string, key []byte, obj any) error { + storage := ObjectContractStorage(obj) if storage != nil { defer func() { log.L().Debug("get object", zap.String("namespace", ns), log.Hex("key", key), zap.String("type", fmt.Sprintf("%T", obj))) @@ -336,9 +336,9 @@ func (store *erigonWorkingSetStore) GetObject(ns string, key []byte, obj any) er return state.Deserialize(obj, value) } -func (store *erigonWorkingSetStore) Get(ns string, key []byte) ([]byte, error) { +func (store *ErigonWorkingSetStore) Get(ns string, key []byte) ([]byte, error) { switch ns { - case AccountKVNamespace: + case state.AccountKVNamespace: accProto := &accountpb.Account{} addr := libcommon.Address(key) if !store.intraBlockState.Exist(addr) { @@ -364,8 +364,8 @@ func (store *erigonWorkingSetStore) Get(ns string, key []byte) ([]byte, error) { } } -func (store *erigonWorkingSetStore) DeleteObject(ns string, key []byte, obj any) error { - storage := store.objectContractStorage(obj) +func (store *ErigonWorkingSetStore) DeleteObject(ns string, key []byte, obj any) error { + storage := ObjectContractStorage(obj) if storage != nil { log.L().Debug("delete object", zap.String("namespace", ns), log.Hex("key", key), zap.String("type", fmt.Sprintf("%T", obj))) return storage.DeleteFromContract(ns, key, store.newContractBackend(store.ctx, store.intraBlockState, store.sr)) @@ -373,22 +373,22 @@ func (store *erigonWorkingSetStore) DeleteObject(ns string, key []byte, obj any) return nil } -func (store *erigonWorkingSetStore) Delete(ns string, key []byte) error { +func (store *ErigonWorkingSetStore) Delete(ns string, key []byte) error { return nil } -func (store *erigonWorkingSetStore) WriteBatch(batch.KVStoreBatch) error { +func (store *ErigonWorkingSetStore) WriteBatch(batch.KVStoreBatch) error { return nil } -func (store *erigonWorkingSetStore) Filter(string, db.Condition, []byte, []byte) ([][]byte, [][]byte, error) { +func (store *ErigonWorkingSetStore) Filter(string, db.Condition, []byte, []byte) ([][]byte, [][]byte, error) { return nil, nil, nil } -func (store *erigonWorkingSetStore) States(ns string, keys [][]byte, obj any) ([][]byte, [][]byte, error) { - storage := store.objectContractStorage(obj) +func (store *ErigonWorkingSetStore) States(ns string, keys [][]byte, obj any) ([][]byte, [][]byte, error) { + storage := ObjectContractStorage(obj) if storage == nil { - return nil, nil, errors.Wrapf(ErrNotSupported, "unsupported object type %T in ns %s", obj, ns) + return nil, nil, errors.Errorf("unsupported object type %T in ns %s", obj, ns) } var ( objs []any @@ -430,15 +430,15 @@ func (store *erigonWorkingSetStore) States(ns string, keys [][]byte, obj any) ([ return keys, results, nil } -func (store *erigonWorkingSetStore) Digest() hash.Hash256 { +func (store *ErigonWorkingSetStore) Digest() hash.Hash256 { return hash.ZeroHash256 } -func (store *erigonWorkingSetStore) CreateGenesisStates(ctx context.Context) error { +func (store *ErigonWorkingSetStore) CreateGenesisStates(ctx context.Context) error { return systemcontracts.DeploySystemContractsIfNotExist(store.newContractBackend(ctx, store.intraBlockState, store.sr)) } -func (store *erigonDB) Height() (uint64, error) { +func (store *ErigonDB) Height() (uint64, error) { var height uint64 err := store.rw.View(context.Background(), func(tx kv.Tx) error { heightBytes, err := tx.GetOne(systemNS, heightKey) @@ -459,7 +459,7 @@ func (store *erigonDB) Height() (uint64, error) { return height, nil } -func (store *erigonWorkingSetStore) newContractBackend(ctx context.Context, intraBlockState *erigonstate.IntraBlockState, sr erigonstate.StateReader) *contractBacked { +func (store *ErigonWorkingSetStore) newContractBackend(ctx context.Context, intraBlockState *erigonstate.IntraBlockState, sr erigonstate.StateReader) *contractBacked { blkCtx := protocol.MustGetBlockCtx(ctx) g, ok := genesis.ExtractGenesisContext(ctx) if !ok { @@ -469,19 +469,23 @@ func (store *erigonWorkingSetStore) newContractBackend(ctx context.Context, intr return NewContractBackend(store.intraBlockState, store.sr, blkCtx.BlockHeight, blkCtx.BlockTimeStamp, &g, bcCtx.EvmNetworkID) } -func (store *erigonWorkingSetStore) objectContractStorage(obj any) state.ContractStorage { - if cs, ok := obj.(state.ContractStorage); ok { +func (store *ErigonWorkingSetStore) KVStore() db.KVStore { + return nil +} + +func (store *ErigonWorkingSetStore) IntraBlockState() *erigonstate.IntraBlockState { + return store.intraBlockState +} + +func ObjectContractStorage(obj any) ContractStorage { + if cs, ok := obj.(ContractStorage); ok { return cs } - if cs, ok := obj.(state.ContractStorageProxy); ok { + if cs, ok := obj.(ContractStorageProxy); ok { return cs.ContractStorageProxy() } - if cs, ok := obj.(state.ContractStorageStandard); ok { - return state.NewContractStorageStandardWrapper(cs) + if cs, ok := obj.(ContractStorageStandard); ok { + return NewContractStorageStandardWrapper(cs) } return nil } - -func (store *erigonWorkingSetStore) KVStore() db.KVStore { - return nil -} diff --git a/state/factory/statedb.go b/state/factory/statedb.go index de98e315fe..a3f6915d40 100644 --- a/state/factory/statedb.go +++ b/state/factory/statedb.go @@ -32,6 +32,7 @@ import ( "github.com/iotexproject/iotex-core/v2/pkg/log" "github.com/iotexproject/iotex-core/v2/pkg/prometheustimer" "github.com/iotexproject/iotex-core/v2/state" + "github.com/iotexproject/iotex-core/v2/state/factory/erigonstore" ) type ( @@ -54,7 +55,7 @@ type ( protocolViews *protocol.Views skipBlockValidationOnPut bool ps *patchStore - erigonDB *erigonDB + erigonDB *erigonstore.ErigonDB } ) @@ -120,7 +121,7 @@ func NewStateDB(cfg Config, dao db.KVStore, opts ...StateDBOption) (Factory, err } sdb.timerFactory = timerFactory if len(cfg.Chain.HistoryIndexPath) > 0 { - sdb.erigonDB = newErigonDB(cfg.Chain.HistoryIndexPath) + sdb.erigonDB = erigonstore.NewErigonDB(cfg.Chain.HistoryIndexPath) } return &sdb, nil @@ -225,7 +226,7 @@ func (sdb *stateDB) newWorkingSet(ctx context.Context, height uint64) (*workingS if sdb.erigonDB == nil { return ws, nil } - e, err := sdb.erigonDB.newErigonStore(ctx, height) + e, err := sdb.erigonDB.NewErigonStore(ctx, height) if err != nil { return nil, err } @@ -366,7 +367,7 @@ func (sdb *stateDB) WorkingSetAtTransaction(ctx context.Context, height uint64, return nil, err } if sdb.erigonDB != nil { - e, err := sdb.erigonDB.newErigonStoreDryrun(ctx, height) + e, err := sdb.erigonDB.NewErigonStoreDryrun(ctx, height) if err != nil { return nil, err } @@ -406,7 +407,7 @@ func (sdb *stateDB) WorkingSetAtHeight(ctx context.Context, height uint64) (prot ) } } - e, err := sdb.erigonDB.newErigonStoreDryrun(ctx, height+1) + e, err := sdb.erigonDB.NewErigonStoreDryrun(ctx, height+1) if err != nil { return nil, err } diff --git a/state/factory/workingset.go b/state/factory/workingset.go index 39c4bda4ae..c59e780cb2 100644 --- a/state/factory/workingset.go +++ b/state/factory/workingset.go @@ -34,6 +34,7 @@ import ( "github.com/iotexproject/iotex-core/v2/db" "github.com/iotexproject/iotex-core/v2/pkg/log" "github.com/iotexproject/iotex-core/v2/state" + "github.com/iotexproject/iotex-core/v2/state/factory/erigonstore" ) var ( @@ -1044,12 +1045,12 @@ func (ws *workingSet) Close() { func (ws *workingSet) Erigon() (*erigonstate.IntraBlockState, bool) { switch st := ws.store.(type) { case *workingSetStoreWithSecondary: - if wss, ok := st.writerSecondary.(*erigonWorkingSetStore); ok { - return wss.intraBlockState, false + if wss, ok := st.writerSecondary.(*erigonstore.ErigonWorkingSetStore); ok { + return wss.IntraBlockState(), false } return nil, false case *erigonWorkingSetStoreForSimulate: - return st.erigonStore.intraBlockState, true + return st.erigonStore.(*erigonstore.ErigonWorkingSetStore).IntraBlockState(), true default: return nil, false } diff --git a/state/factory/workingsetstore_erigon_simulate.go b/state/factory/workingsetstore_erigon_simulate.go index 63b43da451..2c99f667ec 100644 --- a/state/factory/workingsetstore_erigon_simulate.go +++ b/state/factory/workingsetstore_erigon_simulate.go @@ -8,6 +8,7 @@ import ( "github.com/iotexproject/iotex-core/v2/action/protocol/execution/evm" "github.com/iotexproject/iotex-core/v2/db" "github.com/iotexproject/iotex-core/v2/state" + "github.com/iotexproject/iotex-core/v2/state/factory/erigonstore" ) // erigonWorkingSetStoreForSimulate is a working set store that uses erigon as the main store @@ -16,10 +17,10 @@ import ( type erigonWorkingSetStoreForSimulate struct { writer store workingSetStore // fallback to statedb for staking, rewarding and poll - erigonStore *erigonWorkingSetStore + erigonStore workingSetStore } -func newErigonWorkingSetStoreForSimulate(store workingSetStore, erigonStore *erigonWorkingSetStore) *erigonWorkingSetStoreForSimulate { +func newErigonWorkingSetStoreForSimulate(store workingSetStore, erigonStore workingSetStore) *erigonWorkingSetStoreForSimulate { return &erigonWorkingSetStoreForSimulate{ store: store, erigonStore: erigonStore, @@ -36,7 +37,8 @@ func (store *erigonWorkingSetStoreForSimulate) Stop(context.Context) error { } func (store *erigonWorkingSetStoreForSimulate) GetObject(ns string, key []byte, obj any) error { - if _, ok := obj.(state.ContractStorage); ok { + storage := erigonstore.ObjectContractStorage(obj) + if storage != nil { return store.erigonStore.GetObject(ns, key, obj) } if _, ok := obj.(*state.Account); !ok && ns == AccountKVNamespace { @@ -51,7 +53,8 @@ func (store *erigonWorkingSetStoreForSimulate) GetObject(ns string, key []byte, } func (store *erigonWorkingSetStoreForSimulate) States(ns string, keys [][]byte, obj any) ([][]byte, [][]byte, error) { - if _, ok := obj.(state.ContractStorage); ok { + storage := erigonstore.ObjectContractStorage(obj) + if storage != nil { return store.erigonStore.States(ns, keys, obj) } // currently only used for staking & poll, no need to read from erigon From ffe12f8eaf4cca2b590799f4a355a0fd713e6f8c Mon Sep 17 00:00:00 2001 From: envestcc Date: Thu, 11 Sep 2025 16:54:36 +0800 Subject: [PATCH 13/26] store account as contract storage --- api/coreservice.go | 11 +- state/account.go | 35 ++++++ state/factory/erigonstore/contract_backend.go | 35 ++++++ state/factory/erigonstore/contract_storage.go | 14 ++- .../contract_storage_namespaced.go | 12 +- .../erigonstore/contract_storage_standard.go | 12 +- .../erigonstore/workingsetstore_erigon.go | 108 +++--------------- state/state.go | 9 ++ 8 files changed, 123 insertions(+), 113 deletions(-) diff --git a/api/coreservice.go b/api/coreservice.go index 872154ad6f..3f1a45be26 100644 --- a/api/coreservice.go +++ b/api/coreservice.go @@ -359,10 +359,18 @@ func (core *coreService) BalanceAt(ctx context.Context, addr address.Address, he ctx, span := tracer.NewSpan(context.Background(), "coreService.BalanceAt") defer span.End() addrStr := addr.String() + if height == 0 { + height = core.bc.TipHeight() + } ctx, err := core.bc.ContextAtHeight(ctx, height) if err != nil { return "", status.Error(codes.Internal, err.Error()) } + bcCtx := protocol.MustGetBlockchainCtx(ctx) + ctx = protocol.WithBlockCtx(ctx, protocol.BlockCtx{ + BlockHeight: bcCtx.Tip.Height, + BlockTimeStamp: bcCtx.Tip.Timestamp, + }) if addrStr == address.RewardingPoolAddr || addrStr == address.StakingBucketPoolAddr || addrStr == address.RewardingProtocol || addrStr == address.StakingProtocolAddr { acc, _, err := core.getProtocolAccount(ctx, addrStr) @@ -372,9 +380,6 @@ func (core *coreService) BalanceAt(ctx context.Context, addr address.Address, he return acc.Balance, nil } - if height == 0 { - height = core.bc.TipHeight() - } ws, err := core.sf.WorkingSetAtHeight(ctx, height) if err != nil { return "", status.Error(codes.Internal, err.Error()) diff --git a/state/account.go b/state/account.go index 9341432015..ef9a7baaa1 100644 --- a/state/account.go +++ b/state/account.go @@ -9,6 +9,7 @@ import ( "math/big" "github.com/iotexproject/go-pkgs/hash" + "github.com/iotexproject/iotex-address/address" "github.com/pkg/errors" "google.golang.org/protobuf/proto" @@ -271,6 +272,40 @@ func (st *Account) Clone() *Account { return &s } +func (st *Account) StoreToContract(ns string, key []byte, backend ContractBackend) error { + addr, err := address.FromBytes(key) + if err != nil { + return errors.Wrapf(err, "failed to convert key to address %x", key) + } + backend.PutAccount(addr, st) + return nil +} + +func (st *Account) LoadFromContract(ns string, key []byte, backend ContractBackend) error { + addr, err := address.FromBytes(key) + if err != nil { + return errors.Wrapf(err, "failed to convert key to address %x", key) + } + acc, err := backend.Account(addr) + if err != nil { + return err + } + *st = *acc + return nil +} + +func (st *Account) DeleteFromContract(ns string, key []byte, backend ContractBackend) error { + return errors.New("not implemented") +} + +func (st *Account) ListFromContract(ns string, backend ContractBackend) ([][]byte, []any, error) { + return nil, nil, errors.New("not implemented") +} + +func (st *Account) BatchFromContract(ns string, keys [][]byte, backend ContractBackend) ([]any, error) { + return nil, errors.New("not implemented") +} + // NewAccount creates a new account with options func NewAccount(opts ...AccountCreationOption) (*Account, error) { account := &Account{ diff --git a/state/factory/erigonstore/contract_backend.go b/state/factory/erigonstore/contract_backend.go index 29a9a9d3c9..27c82eb48b 100644 --- a/state/factory/erigonstore/contract_backend.go +++ b/state/factory/erigonstore/contract_backend.go @@ -25,6 +25,7 @@ import ( iotexevm "github.com/iotexproject/iotex-core/v2/action/protocol/execution/evm" "github.com/iotexproject/iotex-core/v2/blockchain/genesis" "github.com/iotexproject/iotex-core/v2/pkg/log" + "github.com/iotexproject/iotex-core/v2/state" ) type ( @@ -94,6 +95,40 @@ func (backend *contractBacked) Exists(addr address.Address) bool { return backend.intraBlockState.Exist(erigonComm.BytesToAddress(addr.Bytes())) } +func (backend *contractBacked) PutAccount(_addr address.Address, acc *state.Account) { + addr := erigonComm.BytesToAddress(_addr.Bytes()) + if !backend.intraBlockState.Exist(addr) { + backend.intraBlockState.CreateAccount(addr, acc.IsContract()) + } + backend.intraBlockState.SetBalance(addr, uint256.MustFromBig(acc.Balance)) + ctx := protocol.WithFeatureCtx(protocol.WithBlockCtx(genesis.WithGenesisContext(context.Background(), *backend.g), protocol.BlockCtx{BlockHeight: backend.height})) + fCtx := protocol.MustGetFeatureCtx(ctx) + nonce := acc.PendingNonce() + if fCtx.UseZeroNonceForFreshAccount { + nonce = acc.PendingNonceConsideringFreshAccount() + } + backend.intraBlockState.SetNonce(addr, nonce) +} + +func (backend *contractBacked) Account(_addr address.Address) (*state.Account, error) { + addr := erigonComm.BytesToAddress(_addr.Bytes()) + if !backend.intraBlockState.Exist(addr) { + return nil, errors.Wrapf(state.ErrStateNotExist, "address: %x", addr.Bytes()) + } + balance := backend.intraBlockState.GetBalance(addr) + nonce := backend.intraBlockState.GetNonce(addr) + acc, err := state.NewAccount() + if err != nil { + return nil, errors.Wrap(err, "failed to create account") + } + acc.AddBalance(balance.ToBig()) + acc.SetPendingNonce(nonce) + if ch := backend.intraBlockState.GetCodeHash(addr); len(ch) > 0 { + acc.CodeHash = ch.Bytes() + } + return acc, nil +} + func (backend *contractBacked) prepare(intra evmtypes.IntraBlockState) (*vm.EVM, error) { // deploy system contracts diff --git a/state/factory/erigonstore/contract_storage.go b/state/factory/erigonstore/contract_storage.go index 7ec3679c12..3d187bad6b 100644 --- a/state/factory/erigonstore/contract_storage.go +++ b/state/factory/erigonstore/contract_storage.go @@ -3,16 +3,18 @@ package erigonstore import ( "github.com/iotexproject/iotex-address/address" - "github.com/iotexproject/iotex-core/v2/systemcontracts" + "github.com/iotexproject/iotex-core/v2/state" ) +type ContractBackend = state.ContractBackend + // ContractStorage defines the interface for contract storage operations type ContractStorage interface { - StoreToContract(ns string, key []byte, backend systemcontracts.ContractBackend) error - LoadFromContract(ns string, key []byte, backend systemcontracts.ContractBackend) error - DeleteFromContract(ns string, key []byte, backend systemcontracts.ContractBackend) error - ListFromContract(ns string, backend systemcontracts.ContractBackend) ([][]byte, []any, error) - BatchFromContract(ns string, keys [][]byte, backend systemcontracts.ContractBackend) ([]any, error) + StoreToContract(ns string, key []byte, backend ContractBackend) error + LoadFromContract(ns string, key []byte, backend ContractBackend) error + DeleteFromContract(ns string, key []byte, backend ContractBackend) error + ListFromContract(ns string, backend ContractBackend) ([][]byte, []any, error) + BatchFromContract(ns string, keys [][]byte, backend ContractBackend) ([]any, error) } // ContractStorageStandard defines the interface for standard contract storage operations diff --git a/state/factory/erigonstore/contract_storage_namespaced.go b/state/factory/erigonstore/contract_storage_namespaced.go index 2c185ac153..59293c5b0f 100644 --- a/state/factory/erigonstore/contract_storage_namespaced.go +++ b/state/factory/erigonstore/contract_storage_namespaced.go @@ -20,7 +20,7 @@ func NewContractStorageNamespacedWrapper(standard ContractStorageStandard) Contr return &contractStorageNamespacedWrapper{standard: standard} } -func (cs *contractStorageNamespacedWrapper) StoreToContract(ns string, key []byte, backend systemcontracts.ContractBackend) error { +func (cs *contractStorageNamespacedWrapper) StoreToContract(ns string, key []byte, backend ContractBackend) error { contract, err := cs.storageContract(ns, key, backend) if err != nil { return err @@ -36,7 +36,7 @@ func (cs *contractStorageNamespacedWrapper) StoreToContract(ns string, key []byt return nil } -func (cs *contractStorageNamespacedWrapper) LoadFromContract(ns string, key []byte, backend systemcontracts.ContractBackend) error { +func (cs *contractStorageNamespacedWrapper) LoadFromContract(ns string, key []byte, backend ContractBackend) error { contract, err := cs.storageContract(ns, key, backend) if err != nil { return err @@ -55,7 +55,7 @@ func (cs *contractStorageNamespacedWrapper) LoadFromContract(ns string, key []by return nil } -func (cs *contractStorageNamespacedWrapper) DeleteFromContract(ns string, key []byte, backend systemcontracts.ContractBackend) error { +func (cs *contractStorageNamespacedWrapper) DeleteFromContract(ns string, key []byte, backend ContractBackend) error { contract, err := cs.storageContract(ns, key, backend) if err != nil { return err @@ -67,7 +67,7 @@ func (cs *contractStorageNamespacedWrapper) DeleteFromContract(ns string, key [] return nil } -func (cs *contractStorageNamespacedWrapper) ListFromContract(ns string, backend systemcontracts.ContractBackend) ([][]byte, []any, error) { +func (cs *contractStorageNamespacedWrapper) ListFromContract(ns string, backend ContractBackend) ([][]byte, []any, error) { contract, err := cs.storageContract(ns, nil, backend) if err != nil { return nil, nil, err @@ -96,7 +96,7 @@ func (cs *contractStorageNamespacedWrapper) ListFromContract(ns string, backend return listResult.KeyList, indices, nil } -func (cs *contractStorageNamespacedWrapper) BatchFromContract(ns string, keys [][]byte, backend systemcontracts.ContractBackend) ([]any, error) { +func (cs *contractStorageNamespacedWrapper) BatchFromContract(ns string, keys [][]byte, backend ContractBackend) ([]any, error) { contract, err := cs.storageContract(ns, nil, backend) if err != nil { return nil, err @@ -121,7 +121,7 @@ func (cs *contractStorageNamespacedWrapper) BatchFromContract(ns string, keys [] return results, nil } -func (cs *contractStorageNamespacedWrapper) storageContract(ns string, key []byte, backend systemcontracts.ContractBackend) (*systemcontracts.NamespaceStorageContract, error) { +func (cs *contractStorageNamespacedWrapper) storageContract(ns string, key []byte, backend ContractBackend) (*systemcontracts.NamespaceStorageContract, error) { addr, err := cs.standard.ContractStorageAddress(ns, key) if err != nil { return nil, err diff --git a/state/factory/erigonstore/contract_storage_standard.go b/state/factory/erigonstore/contract_storage_standard.go index 16d5ac722a..ddd8a3c7e2 100644 --- a/state/factory/erigonstore/contract_storage_standard.go +++ b/state/factory/erigonstore/contract_storage_standard.go @@ -17,7 +17,7 @@ func NewContractStorageStandardWrapper(standard ContractStorageStandard) Contrac return &contractStorageStandardWrapper{standard: standard} } -func (cs *contractStorageStandardWrapper) StoreToContract(ns string, key []byte, backend systemcontracts.ContractBackend) error { +func (cs *contractStorageStandardWrapper) StoreToContract(ns string, key []byte, backend ContractBackend) error { contract, err := cs.storageContract(ns, key, backend) if err != nil { return err @@ -32,7 +32,7 @@ func (cs *contractStorageStandardWrapper) StoreToContract(ns string, key []byte, return nil } -func (cs *contractStorageStandardWrapper) LoadFromContract(ns string, key []byte, backend systemcontracts.ContractBackend) error { +func (cs *contractStorageStandardWrapper) LoadFromContract(ns string, key []byte, backend ContractBackend) error { contract, err := cs.storageContract(ns, key, backend) if err != nil { return err @@ -50,7 +50,7 @@ func (cs *contractStorageStandardWrapper) LoadFromContract(ns string, key []byte return nil } -func (cs *contractStorageStandardWrapper) DeleteFromContract(ns string, key []byte, backend systemcontracts.ContractBackend) error { +func (cs *contractStorageStandardWrapper) DeleteFromContract(ns string, key []byte, backend ContractBackend) error { contract, err := cs.storageContract(ns, key, backend) if err != nil { return err @@ -61,7 +61,7 @@ func (cs *contractStorageStandardWrapper) DeleteFromContract(ns string, key []by return nil } -func (cs *contractStorageStandardWrapper) ListFromContract(ns string, backend systemcontracts.ContractBackend) ([][]byte, []any, error) { +func (cs *contractStorageStandardWrapper) ListFromContract(ns string, backend ContractBackend) ([][]byte, []any, error) { contract, err := cs.storageContract(ns, nil, backend) if err != nil { return nil, nil, err @@ -90,7 +90,7 @@ func (cs *contractStorageStandardWrapper) ListFromContract(ns string, backend sy return listResult.KeyList, indices, nil } -func (cs *contractStorageStandardWrapper) BatchFromContract(ns string, keys [][]byte, backend systemcontracts.ContractBackend) ([]any, error) { +func (cs *contractStorageStandardWrapper) BatchFromContract(ns string, keys [][]byte, backend ContractBackend) ([]any, error) { contract, err := cs.storageContract(ns, nil, backend) if err != nil { return nil, err @@ -115,7 +115,7 @@ func (cs *contractStorageStandardWrapper) BatchFromContract(ns string, keys [][] return results, nil } -func (cs *contractStorageStandardWrapper) storageContract(ns string, key []byte, backend systemcontracts.ContractBackend) (*systemcontracts.GenericStorageContract, error) { +func (cs *contractStorageStandardWrapper) storageContract(ns string, key []byte, backend ContractBackend) (*systemcontracts.GenericStorageContract, error) { addr, err := cs.standard.ContractStorageAddress(ns, key) if err != nil { return nil, err diff --git a/state/factory/erigonstore/workingsetstore_erigon.go b/state/factory/erigonstore/workingsetstore_erigon.go index fce6f60825..7e5c0401f5 100644 --- a/state/factory/erigonstore/workingsetstore_erigon.go +++ b/state/factory/erigonstore/workingsetstore_erigon.go @@ -5,7 +5,6 @@ import ( "fmt" "math/big" - libcommon "github.com/erigontech/erigon-lib/common" "github.com/erigontech/erigon-lib/common/datadir" "github.com/erigontech/erigon-lib/kv" "github.com/erigontech/erigon-lib/kv/mdbx" @@ -19,16 +18,13 @@ import ( "github.com/holiman/uint256" "github.com/pkg/errors" "go.uber.org/zap" - "google.golang.org/protobuf/proto" "github.com/iotexproject/go-pkgs/hash" "github.com/iotexproject/iotex-core/v2/action/protocol" - "github.com/iotexproject/iotex-core/v2/action/protocol/account/accountpb" "github.com/iotexproject/iotex-core/v2/action/protocol/execution/evm" "github.com/iotexproject/iotex-core/v2/blockchain/genesis" "github.com/iotexproject/iotex-core/v2/db" - "github.com/iotexproject/iotex-core/v2/db/batch" "github.com/iotexproject/iotex-core/v2/pkg/log" "github.com/iotexproject/iotex-core/v2/state" "github.com/iotexproject/iotex-core/v2/systemcontracts" @@ -283,106 +279,34 @@ func (store *ErigonWorkingSetStore) ResetSnapshots() {} func (store *ErigonWorkingSetStore) PutObject(ns string, key []byte, obj any) (err error) { storage := ObjectContractStorage(obj) - if storage != nil { - log.L().Debug("put object", zap.String("namespace", ns), log.Hex("key", key), zap.String("type", fmt.Sprintf("%T", obj)), zap.Any("content", obj)) - return storage.StoreToContract(ns, key, store.newContractBackend(store.ctx, store.intraBlockState, store.sr)) - } - value, err := state.Serialize(obj) - if err != nil { - return errors.Wrapf(err, "failed to serialize object for namespace %s and key %x", ns, key) - } - return store.Put(ns, key, value) -} - -func (store *ErigonWorkingSetStore) Put(ns string, key []byte, value []byte) (err error) { - // only handling account, contract storage handled by evm adapter - // others are ignored - if ns != state.AccountKVNamespace { - return nil - } - defer func() { - if r := recover(); r != nil { - log.L().Warn("store no account in account namespace", zap.Any("recover", r), log.Hex("key", key), zap.String("ns", ns), zap.ByteString("value", value)) - err = nil - } - }() - acc := &state.Account{} - if err := acc.Deserialize(value); err != nil { - // should be legacy rewarding funds - log.L().Warn("store no account in account namespace", log.Hex("key", key), zap.String("ns", ns), zap.ByteString("value", value)) + if storage == nil { + // TODO: return error after all types are supported return nil } - addr := libcommon.Address(key) - if !store.intraBlockState.Exist(addr) { - store.intraBlockState.CreateAccount(addr, false) - } - store.intraBlockState.SetBalance(addr, uint256.MustFromBig(acc.Balance)) - store.intraBlockState.SetNonce(addr, acc.PendingNonce()) // TODO(erigon): not sure if this is correct - return nil + log.L().Debug("put object", zap.String("namespace", ns), log.Hex("key", key), zap.String("type", fmt.Sprintf("%T", obj)), zap.Any("content", obj)) + return storage.StoreToContract(ns, key, store.newContractBackend(store.ctx, store.intraBlockState, store.sr)) } func (store *ErigonWorkingSetStore) GetObject(ns string, key []byte, obj any) error { storage := ObjectContractStorage(obj) - if storage != nil { - defer func() { - log.L().Debug("get object", zap.String("namespace", ns), log.Hex("key", key), zap.String("type", fmt.Sprintf("%T", obj))) - }() - return storage.LoadFromContract(ns, key, store.newContractBackend(store.ctx, store.intraBlockState, store.sr)) - } - value, err := store.Get(ns, key) - if err != nil { - return errors.Wrapf(err, "failed to get object for namespace %s and key %x", ns, key) - } - return state.Deserialize(obj, value) -} - -func (store *ErigonWorkingSetStore) Get(ns string, key []byte) ([]byte, error) { - switch ns { - case state.AccountKVNamespace: - accProto := &accountpb.Account{} - addr := libcommon.Address(key) - if !store.intraBlockState.Exist(addr) { - return nil, state.ErrStateNotExist - } - balance := store.intraBlockState.GetBalance(addr) - accProto.Balance = balance.String() - nonce := store.intraBlockState.GetNonce(addr) - accProto.Nonce = nonce - accProto.Type = accountpb.AccountType_ZERO_NONCE - if ch := store.intraBlockState.GetCodeHash(addr); len(ch) > 0 { - accProto.CodeHash = store.intraBlockState.GetCodeHash(addr).Bytes() - } - return proto.Marshal(accProto) - case evm.CodeKVNameSpace: - addr := libcommon.Address(key) - if !store.intraBlockState.Exist(addr) { - return nil, state.ErrStateNotExist - } - return store.intraBlockState.GetCode(addr), nil - default: - return nil, errors.Errorf("unexpected erigon get namespace %s, key %x", ns, key) + if storage == nil { + // TODO: return error after all types are supported + return nil } + defer func() { + log.L().Debug("get object", zap.String("namespace", ns), log.Hex("key", key), zap.String("type", fmt.Sprintf("%T", obj))) + }() + return storage.LoadFromContract(ns, key, store.newContractBackend(store.ctx, store.intraBlockState, store.sr)) } func (store *ErigonWorkingSetStore) DeleteObject(ns string, key []byte, obj any) error { storage := ObjectContractStorage(obj) - if storage != nil { - log.L().Debug("delete object", zap.String("namespace", ns), log.Hex("key", key), zap.String("type", fmt.Sprintf("%T", obj))) - return storage.DeleteFromContract(ns, key, store.newContractBackend(store.ctx, store.intraBlockState, store.sr)) + if storage == nil { + // TODO: return error after all types are supported + return nil } - return nil -} - -func (store *ErigonWorkingSetStore) Delete(ns string, key []byte) error { - return nil -} - -func (store *ErigonWorkingSetStore) WriteBatch(batch.KVStoreBatch) error { - return nil -} - -func (store *ErigonWorkingSetStore) Filter(string, db.Condition, []byte, []byte) ([][]byte, [][]byte, error) { - return nil, nil, nil + log.L().Debug("delete object", zap.String("namespace", ns), log.Hex("key", key), zap.String("type", fmt.Sprintf("%T", obj))) + return storage.DeleteFromContract(ns, key, store.newContractBackend(store.ctx, store.intraBlockState, store.sr)) } func (store *ErigonWorkingSetStore) States(ns string, keys [][]byte, obj any) ([][]byte, [][]byte, error) { diff --git a/state/state.go b/state/state.go index 0751fedb68..4be58ce099 100644 --- a/state/state.go +++ b/state/state.go @@ -6,7 +6,10 @@ package state import ( + "github.com/iotexproject/iotex-address/address" "github.com/pkg/errors" + + "github.com/iotexproject/iotex-core/v2/systemcontracts" ) var ( @@ -51,3 +54,9 @@ func Deserialize(x interface{}, data []byte) error { } panic("data holder doesn't implement Deserializer interface!") } + +type ContractBackend interface { + systemcontracts.ContractBackend + PutAccount(addr address.Address, acc *Account) + Account(addr address.Address) (*Account, error) +} From 2209d32c3a910806b10cdc61b6a450f277718a8f Mon Sep 17 00:00:00 2001 From: envestcc Date: Thu, 11 Sep 2025 20:43:54 +0800 Subject: [PATCH 14/26] systemcontract auth --- systemcontracts/GenericStorage.sol | 16 +- systemcontracts/NamespaceStorage.sol | 20 +- systemcontracts/generic_storage.go | 9 + systemcontracts/generic_storage_abi.go | 669 ++++++++------ systemcontracts/namespace_storage.go | 15 + systemcontracts/namespace_storage_abi.go | 1077 ++++++++++++---------- 6 files changed, 1002 insertions(+), 804 deletions(-) diff --git a/systemcontracts/GenericStorage.sol b/systemcontracts/GenericStorage.sol index 1e39583b8f..290afd0a55 100644 --- a/systemcontracts/GenericStorage.sol +++ b/systemcontracts/GenericStorage.sol @@ -1,6 +1,8 @@ // SPDX-License-Identifier: Apache-2.0 pragma solidity ^0.8.0; +import "@openzeppelin/contracts/access/Ownable.sol"; + /** * @title GenericStorage * @dev Generic storage contract for key-value data with flexible value structure @@ -9,8 +11,9 @@ pragma solidity ^0.8.0; * - Batch operations (batchGet) * - Listing all stored data * - Flexible value structure with immutable and mutable fields + * - Owner-only access control for modification operations */ -contract GenericStorage { +contract GenericStorage is Ownable { /** * @dev Generic value structure with multiple fields for flexibility @@ -40,6 +43,11 @@ contract GenericStorage { event BatchDataRetrieved(uint256 keyCount); event StorageCleared(); + /** + * @dev Constructor that sets the deployer as the owner + */ + constructor() Ownable(msg.sender) {} + /** * @dev Internal function to check if a key exists * @param key The storage key to check @@ -57,7 +65,7 @@ contract GenericStorage { function put( bytes memory key, GenericValue memory value - ) external { + ) external onlyOwner { require(key.length > 0, "Key cannot be empty"); // If key doesn't exist, add it to keys array @@ -77,7 +85,7 @@ contract GenericStorage { * @dev Delete data by key * @param key The storage key to delete */ - function remove(bytes memory key) external { + function remove(bytes memory key) external onlyOwner { require(_keyExists(key), "Key does not exist"); // Get the index of the key to remove (subtract 1 since we stored index + 1) @@ -227,7 +235,7 @@ contract GenericStorage { * @dev Clear all stored data (emergency function) * Note: This function should be carefully protected in production */ - function clear() external { + function clear() external onlyOwner { // Clear all mappings and arrays for (uint256 i = 0; i < keys_.length; i++) { bytes memory key = keys_[i]; diff --git a/systemcontracts/NamespaceStorage.sol b/systemcontracts/NamespaceStorage.sol index cfc8c767a1..38233e9a6c 100644 --- a/systemcontracts/NamespaceStorage.sol +++ b/systemcontracts/NamespaceStorage.sol @@ -1,12 +1,15 @@ // SPDX-License-Identifier: Apache-2.0 pragma solidity ^0.8.0; +import "@openzeppelin/contracts/access/Ownable.sol"; + /** * @title NamespaceStorage * @dev Namespace-aware storage contract for key-value data with flexible value structure * This contract extends the GenericStorage concept with namespace support for data isolation + * - Owner-only access control for modification operations */ -contract NamespaceStorage { +contract NamespaceStorage is Ownable { /** * @dev Generic value structure with multiple fields for flexibility @@ -39,6 +42,11 @@ contract NamespaceStorage { event NamespaceCleared(string indexed namespace); event AllDataCleared(); + /** + * @dev Constructor that sets the deployer as the owner + */ + constructor() Ownable(msg.sender) {} + /** * @dev Internal function to check if a key exists in a namespace * @param namespace The namespace to check @@ -59,7 +67,7 @@ contract NamespaceStorage { string memory namespace, bytes memory key, GenericValue memory value - ) external { + ) external onlyOwner { require(bytes(namespace).length > 0, "Namespace cannot be empty"); require(key.length > 0, "Key cannot be empty"); @@ -105,7 +113,7 @@ contract NamespaceStorage { * @param namespace The namespace containing the key * @param key The storage key to delete */ - function remove(string memory namespace, bytes memory key) external { + function remove(string memory namespace, bytes memory key) external onlyOwner { require(namespaceExists_[namespace], "Namespace does not exist"); require(_keyExists(namespace, key), "Key does not exist in namespace"); @@ -162,7 +170,7 @@ contract NamespaceStorage { string memory namespace, bytes[] memory keys, GenericValue[] memory values - ) external { + ) external onlyOwner { require(keys.length == values.length, "Keys and values arrays must have same length"); require(bytes(namespace).length > 0, "Namespace cannot be empty"); @@ -349,7 +357,7 @@ contract NamespaceStorage { * @dev Clear all data in a specific namespace * @param namespace The namespace to clear */ - function clearNamespace(string memory namespace) external { + function clearNamespace(string memory namespace) external onlyOwner { require(namespaceExists_[namespace], "Namespace does not exist"); bytes[] storage keys = namespaceKeys_[namespace]; @@ -370,7 +378,7 @@ contract NamespaceStorage { * @dev Clear all stored data across all namespaces (emergency function) * Note: This function should be carefully protected in production */ - function clearAll() external { + function clearAll() external onlyOwner { // Clear all namespaces for (uint256 i = 0; i < namespaces_.length; i++) { string memory namespace = namespaces_[i]; diff --git a/systemcontracts/generic_storage.go b/systemcontracts/generic_storage.go index 66163ed0c5..33d69d1e61 100644 --- a/systemcontracts/generic_storage.go +++ b/systemcontracts/generic_storage.go @@ -86,6 +86,7 @@ func (g *GenericStorageContract) Put(key []byte, value GenericValue) error { // Execute the transaction callMsg := ðereum.CallMsg{ + From: common.BytesToAddress(systemContractCreatorAddr[:]), To: &g.contractAddress, Data: data, Value: big.NewInt(0), @@ -130,6 +131,7 @@ func (g *GenericStorageContract) Get(key []byte) (*GetResult, error) { // Execute the call callMsg := ðereum.CallMsg{ + From: common.BytesToAddress(systemContractCreatorAddr[:]), To: &g.contractAddress, Data: data, Value: big.NewInt(0), @@ -177,6 +179,7 @@ func (g *GenericStorageContract) Remove(key []byte) error { // Execute the transaction callMsg := ðereum.CallMsg{ + From: common.BytesToAddress(systemContractCreatorAddr[:]), To: &g.contractAddress, Data: data, Value: big.NewInt(0), @@ -211,6 +214,7 @@ func (g *GenericStorageContract) BatchGet(keys [][]byte) (*BatchGetResult, error // Execute the call callMsg := ðereum.CallMsg{ + From: common.BytesToAddress(systemContractCreatorAddr[:]), To: &g.contractAddress, Data: data, Value: big.NewInt(0), @@ -253,6 +257,7 @@ func (g *GenericStorageContract) List(offset, limit uint64) (*ListResult, error) // Execute the call callMsg := ðereum.CallMsg{ + From: common.BytesToAddress(systemContractCreatorAddr[:]), To: &g.contractAddress, Data: data, Value: big.NewInt(0), @@ -299,6 +304,7 @@ func (g *GenericStorageContract) ListKeys(offset, limit uint64) (*ListKeysResult // Execute the call callMsg := ðereum.CallMsg{ + From: common.BytesToAddress(systemContractCreatorAddr[:]), To: &g.contractAddress, Data: data, Value: big.NewInt(0), @@ -348,6 +354,7 @@ func (g *GenericStorageContract) Exists(key []byte) (bool, error) { // Execute the call callMsg := ðereum.CallMsg{ + From: common.BytesToAddress(systemContractCreatorAddr[:]), To: &g.contractAddress, Data: data, Value: big.NewInt(0), @@ -386,6 +393,7 @@ func (g *GenericStorageContract) Count() (*big.Int, error) { // Execute the call callMsg := ðereum.CallMsg{ + From: common.BytesToAddress(systemContractCreatorAddr[:]), To: &g.contractAddress, Data: data, Value: big.NewInt(0), @@ -423,6 +431,7 @@ func (g *GenericStorageContract) Clear() error { // Execute the transaction callMsg := ðereum.CallMsg{ + From: common.BytesToAddress(systemContractCreatorAddr[:]), To: &g.contractAddress, Data: data, Value: big.NewInt(0), diff --git a/systemcontracts/generic_storage_abi.go b/systemcontracts/generic_storage_abi.go index c61721a860..5b271a8deb 100644 --- a/systemcontracts/generic_storage_abi.go +++ b/systemcontracts/generic_storage_abi.go @@ -2,300 +2,379 @@ package systemcontracts // GenericStorageABI is the ABI definition for the GenericStorage contract const GenericStorageABI = `[ - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes", - "name": "key", - "type": "bytes" - } - ], - "name": "DataDeleted", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes", - "name": "key", - "type": "bytes" - } - ], - "name": "DataStored", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "keyCount", - "type": "uint256" - } - ], - "name": "BatchDataRetrieved", - "type": "event" - }, - { - "anonymous": false, - "inputs": [], - "name": "StorageCleared", - "type": "event" - }, - { - "inputs": [ - { - "internalType": "bytes[]", - "name": "keyList", - "type": "bytes[]" - } - ], - "name": "batchGet", - "outputs": [ - { - "components": [ - { - "internalType": "bytes", - "name": "primaryData", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "secondaryData", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "auxiliaryData", - "type": "bytes" - } - ], - "internalType": "struct GenericStorage.GenericValue[]", - "name": "values", - "type": "tuple[]" - }, - { - "internalType": "bool[]", - "name": "existsFlags", - "type": "bool[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "clear", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "count", - "outputs": [ - { - "internalType": "uint256", - "name": "totalCount", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "key", - "type": "bytes" - } - ], - "name": "exists", - "outputs": [ - { - "internalType": "bool", - "name": "keyExists", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "key", - "type": "bytes" - } - ], - "name": "get", - "outputs": [ - { - "components": [ - { - "internalType": "bytes", - "name": "primaryData", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "secondaryData", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "auxiliaryData", - "type": "bytes" - } - ], - "internalType": "struct GenericStorage.GenericValue", - "name": "value", - "type": "tuple" - }, - { - "internalType": "bool", - "name": "keyExists", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "offset", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "limit", - "type": "uint256" - } - ], - "name": "list", - "outputs": [ - { - "internalType": "bytes[]", - "name": "keyList", - "type": "bytes[]" - }, - { - "components": [ - { - "internalType": "bytes", - "name": "primaryData", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "secondaryData", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "auxiliaryData", - "type": "bytes" - } - ], - "internalType": "struct GenericStorage.GenericValue[]", - "name": "values", - "type": "tuple[]" - }, - { - "internalType": "uint256", - "name": "total", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "offset", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "limit", - "type": "uint256" - } - ], - "name": "listKeys", - "outputs": [ - { - "internalType": "bytes[]", - "name": "keyList", - "type": "bytes[]" - }, - { - "internalType": "uint256", - "name": "total", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "key", - "type": "bytes" - }, - { - "components": [ - { - "internalType": "bytes", - "name": "primaryData", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "secondaryData", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "auxiliaryData", - "type": "bytes" - } - ], - "internalType": "struct GenericStorage.GenericValue", - "name": "value", - "type": "tuple" - } - ], - "name": "put", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "key", - "type": "bytes" - } - ], - "name": "remove", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } + { + "inputs": [], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "OwnableInvalidOwner", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "OwnableUnauthorizedAccount", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "keyCount", + "type": "uint256" + } + ], + "name": "BatchDataRetrieved", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes", + "name": "key", + "type": "bytes" + } + ], + "name": "DataDeleted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes", + "name": "key", + "type": "bytes" + } + ], + "name": "DataStored", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [], + "name": "StorageCleared", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "bytes[]", + "name": "keyList", + "type": "bytes[]" + } + ], + "name": "batchGet", + "outputs": [ + { + "components": [ + { + "internalType": "bytes", + "name": "primaryData", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "secondaryData", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "auxiliaryData", + "type": "bytes" + } + ], + "internalType": "struct GenericStorage.GenericValue[]", + "name": "values", + "type": "tuple[]" + }, + { + "internalType": "bool[]", + "name": "existsFlags", + "type": "bool[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "clear", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "count", + "outputs": [ + { + "internalType": "uint256", + "name": "totalCount", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "key", + "type": "bytes" + } + ], + "name": "exists", + "outputs": [ + { + "internalType": "bool", + "name": "keyExists", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "key", + "type": "bytes" + } + ], + "name": "get", + "outputs": [ + { + "components": [ + { + "internalType": "bytes", + "name": "primaryData", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "secondaryData", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "auxiliaryData", + "type": "bytes" + } + ], + "internalType": "struct GenericStorage.GenericValue", + "name": "value", + "type": "tuple" + }, + { + "internalType": "bool", + "name": "keyExists", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "offset", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "limit", + "type": "uint256" + } + ], + "name": "list", + "outputs": [ + { + "internalType": "bytes[]", + "name": "keyList", + "type": "bytes[]" + }, + { + "components": [ + { + "internalType": "bytes", + "name": "primaryData", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "secondaryData", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "auxiliaryData", + "type": "bytes" + } + ], + "internalType": "struct GenericStorage.GenericValue[]", + "name": "values", + "type": "tuple[]" + }, + { + "internalType": "uint256", + "name": "total", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "offset", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "limit", + "type": "uint256" + } + ], + "name": "listKeys", + "outputs": [ + { + "internalType": "bytes[]", + "name": "keyList", + "type": "bytes[]" + }, + { + "internalType": "uint256", + "name": "total", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "key", + "type": "bytes" + }, + { + "components": [ + { + "internalType": "bytes", + "name": "primaryData", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "secondaryData", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "auxiliaryData", + "type": "bytes" + } + ], + "internalType": "struct GenericStorage.GenericValue", + "name": "value", + "type": "tuple" + } + ], + "name": "put", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "key", + "type": "bytes" + } + ], + "name": "remove", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } ]` -const GenericStorageByteCodeStr = "608060405234801561001057600080fd5b50612605806100206000396000f3fe608060405234801561001057600080fd5b50600436106100935760003560e01c806352efea6e1161006657806352efea6e1461013557806358edef4c1461013f57806379fc09a21461015b578063821bef2f1461018b578063d6d7d525146101bc57610093565b806306661abd14610098578063072957b0146100b657806342e1ae2e146100d257806350fd736714610103575b600080fd5b6100a06101ed565b6040516100ad919061179e565b60405180910390f35b6100d060048036038101906100cb91906119d5565b6101f9565b005b6100ec60048036038101906100e79190611b33565b610407565b6040516100fa929190611de5565b60405180910390f35b61011d60048036038101906101189190611e48565b610780565b60405161012c93929190611f4a565b60405180910390f35b61013d610c03565b005b61015960048036038101906101549190611f8f565b610d37565b005b61017560048036038101906101709190611f8f565b611216565b6040516101829190611fe7565b60405180910390f35b6101a560048036038101906101a09190611e48565b611228565b6040516101b3929190612002565b60405180910390f35b6101d660048036038101906101d19190611f8f565b6113f6565b6040516101e4929190612090565b60405180910390f35b60008080549050905090565b600082511161023d576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016102349061211d565b60405180910390fd5b6102468261162c565b61032857600160008054905061025c919061216c565b60028360405161026c91906121dc565b9081526020016040518091039020819055506000829080600181540180825580915050600190039060005260206000200160009091909190915090816102b291906123ff565b50600181908060018154018082558091505060019003906000526020600020906003020160009091909190915060008201518160000190816102f491906123ff565b50602082015181600101908161030a91906123ff565b50604082015181600201908161032091906123ff565b5050506103c1565b6000600160028460405161033c91906121dc565b90815260200160405180910390205461035591906124d1565b9050816001828154811061036c5761036b612505565b5b9060005260206000209060030201600082015181600001908161038f91906123ff565b5060208201518160010190816103a591906123ff565b5060408201518160020190816103bb91906123ff565b50905050505b816040516103cf91906121dc565b60405180910390207f281be1a469724e78f8c4152bcc9fb70a95646c3e1e2ade9293d8d497c976338a60405160405180910390a25050565b606080825167ffffffffffffffff811115610425576104246117e8565b5b60405190808252806020026020018201604052801561045e57816020015b61044b611657565b8152602001906001900390816104435790505b509150825167ffffffffffffffff81111561047c5761047b6117e8565b5b6040519080825280602002602001820160405280156104aa5781602001602082028036833780820191505090505b50905060005b835181101561077a576104dc8482815181106104cf576104ce612505565b5b602002602001015161162c565b8282815181106104ef576104ee612505565b5b60200260200101901515908115158152505081818151811061051457610513612505565b5b60200260200101511561076d5760006001600286848151811061053a57610539612505565b5b602002602001015160405161054f91906121dc565b90815260200160405180910390205461056891906124d1565b90506001818154811061057e5761057d612505565b5b90600052602060002090600302016040518060600160405290816000820180546105a790612222565b80601f01602080910402602001604051908101604052809291908181526020018280546105d390612222565b80156106205780601f106105f557610100808354040283529160200191610620565b820191906000526020600020905b81548152906001019060200180831161060357829003601f168201915b5050505050815260200160018201805461063990612222565b80601f016020809104026020016040519081016040528092919081815260200182805461066590612222565b80156106b25780601f10610687576101008083540402835291602001916106b2565b820191906000526020600020905b81548152906001019060200180831161069557829003601f168201915b505050505081526020016002820180546106cb90612222565b80601f01602080910402602001604051908101604052809291908181526020018280546106f790612222565b80156107445780601f1061071957610100808354040283529160200191610744565b820191906000526020600020905b81548152906001019060200180831161072757829003601f168201915b5050505050815250508483815181106107605761075f612505565b5b6020026020010181905250505b80806001019150506104b0565b50915091565b60608060008080549050905080851061084057600067ffffffffffffffff8111156107ae576107ad6117e8565b5b6040519080825280602002602001820160405280156107e157816020015b60608152602001906001900390816107cc5790505b509250600067ffffffffffffffff8111156107ff576107fe6117e8565b5b60405190808252806020026020018201604052801561083857816020015b610825611657565b81526020019060019003908161081d5790505b509150610bfc565b6000858261084e91906124d1565b9050600081861161085f5785610861565b815b90508067ffffffffffffffff81111561087d5761087c6117e8565b5b6040519080825280602002602001820160405280156108b057816020015b606081526020019060019003908161089b5790505b5094508067ffffffffffffffff8111156108cd576108cc6117e8565b5b60405190808252806020026020018201604052801561090657816020015b6108f3611657565b8152602001906001900390816108eb5790505b50935060005b81811015610bf85760008189610922919061216c565b90506000818154811061093857610937612505565b5b90600052602060002001805461094d90612222565b80601f016020809104026020016040519081016040528092919081815260200182805461097990612222565b80156109c65780601f1061099b576101008083540402835291602001916109c6565b820191906000526020600020905b8154815290600101906020018083116109a957829003601f168201915b50505050508783815181106109de576109dd612505565b5b6020026020010181905250600181815481106109fd576109fc612505565b5b9060005260206000209060030201604051806060016040529081600082018054610a2690612222565b80601f0160208091040260200160405190810160405280929190818152602001828054610a5290612222565b8015610a9f5780601f10610a7457610100808354040283529160200191610a9f565b820191906000526020600020905b815481529060010190602001808311610a8257829003601f168201915b50505050508152602001600182018054610ab890612222565b80601f0160208091040260200160405190810160405280929190818152602001828054610ae490612222565b8015610b315780601f10610b0657610100808354040283529160200191610b31565b820191906000526020600020905b815481529060010190602001808311610b1457829003601f168201915b50505050508152602001600282018054610b4a90612222565b80601f0160208091040260200160405190810160405280929190818152602001828054610b7690612222565b8015610bc35780601f10610b9857610100808354040283529160200191610bc3565b820191906000526020600020905b815481529060010190602001808311610ba657829003601f168201915b505050505081525050868381518110610bdf57610bde612505565b5b602002602001018190525050808060010191505061090c565b5050505b9250925092565b60005b600080549050811015610ced576000808281548110610c2857610c27612505565b5b906000526020600020018054610c3d90612222565b80601f0160208091040260200160405190810160405280929190818152602001828054610c6990612222565b8015610cb65780601f10610c8b57610100808354040283529160200191610cb6565b820191906000526020600020905b815481529060010190602001808311610c9957829003601f168201915b50505050509050600281604051610ccd91906121dc565b908152602001604051809103902060009055508080600101915050610c06565b50600080610cfb9190611678565b60016000610d099190611699565b7f6c7e419df39ff46e811e7d979ebfd916b8d4960de06f479dc69cf8417cdb89e760405160405180910390a1565b610d408161162c565b610d7f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610d7690612580565b60405180910390fd5b60006001600283604051610d9391906121dc565b908152602001604051809103902054610dac91906124d1565b905060006001600080549050610dc291906124d1565b9050808214611122576000808281548110610de057610ddf612505565b5b906000526020600020018054610df590612222565b80601f0160208091040260200160405190810160405280929190818152602001828054610e2190612222565b8015610e6e5780601f10610e4357610100808354040283529160200191610e6e565b820191906000526020600020905b815481529060010190602001808311610e5157829003601f168201915b50505050509050600060018381548110610e8b57610e8a612505565b5b9060005260206000209060030201604051806060016040529081600082018054610eb490612222565b80601f0160208091040260200160405190810160405280929190818152602001828054610ee090612222565b8015610f2d5780601f10610f0257610100808354040283529160200191610f2d565b820191906000526020600020905b815481529060010190602001808311610f1057829003601f168201915b50505050508152602001600182018054610f4690612222565b80601f0160208091040260200160405190810160405280929190818152602001828054610f7290612222565b8015610fbf5780601f10610f9457610100808354040283529160200191610fbf565b820191906000526020600020905b815481529060010190602001808311610fa257829003601f168201915b50505050508152602001600282018054610fd890612222565b80601f016020809104026020016040519081016040528092919081815260200182805461100490612222565b80156110515780601f1061102657610100808354040283529160200191611051565b820191906000526020600020905b81548152906001019060200180831161103457829003601f168201915b5050505050815250509050816000858154811061107157611070612505565b5b90600052602060002001908161108791906123ff565b50806001858154811061109d5761109c612505565b5b906000526020600020906003020160008201518160000190816110c091906123ff565b5060208201518160010190816110d691906123ff565b5060408201518160020190816110ec91906123ff565b509050506001846110fd919061216c565b60028360405161110d91906121dc565b90815260200160405180910390208190555050505b6000805480611134576111336125a0565b5b60019003818190600052602060002001600061115091906116bd565b90556001805480611164576111636125a0565b5b60019003818190600052602060002090600302016000808201600061118991906116bd565b60018201600061119991906116bd565b6002820160006111a991906116bd565b505090556002836040516111bd91906121dc565b908152602001604051809103902060009055826040516111dd91906121dc565b60405180910390207f9248955bf73fd007be0a0d9dc13c36f9e61c3642fbac04d8ac592e0c21d0103760405160405180910390a2505050565b60006112218261162c565b9050919050565b606060008080549050905080841061129057600067ffffffffffffffff811115611255576112546117e8565b5b60405190808252806020026020018201604052801561128857816020015b60608152602001906001900390816112735790505b5091506113ef565b6000848261129e91906124d1565b905060008185116112af57846112b1565b815b90508067ffffffffffffffff8111156112cd576112cc6117e8565b5b60405190808252806020026020018201604052801561130057816020015b60608152602001906001900390816112eb5790505b50935060005b818110156113eb576000818861131c919061216c565b8154811061132d5761132c612505565b5b90600052602060002001805461134290612222565b80601f016020809104026020016040519081016040528092919081815260200182805461136e90612222565b80156113bb5780601f10611390576101008083540402835291602001916113bb565b820191906000526020600020905b81548152906001019060200180831161139e57829003601f168201915b50505050508582815181106113d3576113d2612505565b5b60200260200101819052508080600101915050611306565b5050505b9250929050565b6113fe611657565b60006114098361162c565b90508015611627576000600160028560405161142591906121dc565b90815260200160405180910390205461143e91906124d1565b90506001818154811061145457611453612505565b5b906000526020600020906003020160405180606001604052908160008201805461147d90612222565b80601f01602080910402602001604051908101604052809291908181526020018280546114a990612222565b80156114f65780601f106114cb576101008083540402835291602001916114f6565b820191906000526020600020905b8154815290600101906020018083116114d957829003601f168201915b5050505050815260200160018201805461150f90612222565b80601f016020809104026020016040519081016040528092919081815260200182805461153b90612222565b80156115885780601f1061155d57610100808354040283529160200191611588565b820191906000526020600020905b81548152906001019060200180831161156b57829003601f168201915b505050505081526020016002820180546115a190612222565b80601f01602080910402602001604051908101604052809291908181526020018280546115cd90612222565b801561161a5780601f106115ef5761010080835404028352916020019161161a565b820191906000526020600020905b8154815290600101906020018083116115fd57829003601f168201915b5050505050815250509250505b915091565b60008060028360405161163f91906121dc565b90815260200160405180910390205414159050919050565b60405180606001604052806060815260200160608152602001606081525090565b508054600082559060005260206000209081019061169691906116fd565b50565b50805460008255600302906000526020600020908101906116ba9190611721565b50565b5080546116c990612222565b6000825580601f106116db57506116fa565b601f0160209004906000526020600020908101906116f99190611768565b5b50565b5b8082111561171d576000818161171491906116bd565b506001016116fe565b5090565b5b80821115611764576000808201600061173b91906116bd565b60018201600061174b91906116bd565b60028201600061175b91906116bd565b50600301611722565b5090565b5b80821115611781576000816000905550600101611769565b5090565b6000819050919050565b61179881611785565b82525050565b60006020820190506117b3600083018461178f565b92915050565b6000604051905090565b600080fd5b600080fd5b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b611820826117d7565b810181811067ffffffffffffffff8211171561183f5761183e6117e8565b5b80604052505050565b60006118526117b9565b905061185e8282611817565b919050565b600067ffffffffffffffff82111561187e5761187d6117e8565b5b611887826117d7565b9050602081019050919050565b82818337600083830152505050565b60006118b66118b184611863565b611848565b9050828152602081018484840111156118d2576118d16117d2565b5b6118dd848285611894565b509392505050565b600082601f8301126118fa576118f96117cd565b5b813561190a8482602086016118a3565b91505092915050565b600080fd5b600080fd5b60006060828403121561193357611932611913565b5b61193d6060611848565b9050600082013567ffffffffffffffff81111561195d5761195c611918565b5b611969848285016118e5565b600083015250602082013567ffffffffffffffff81111561198d5761198c611918565b5b611999848285016118e5565b602083015250604082013567ffffffffffffffff8111156119bd576119bc611918565b5b6119c9848285016118e5565b60408301525092915050565b600080604083850312156119ec576119eb6117c3565b5b600083013567ffffffffffffffff811115611a0a57611a096117c8565b5b611a16858286016118e5565b925050602083013567ffffffffffffffff811115611a3757611a366117c8565b5b611a438582860161191d565b9150509250929050565b600067ffffffffffffffff821115611a6857611a676117e8565b5b602082029050602081019050919050565b600080fd5b6000611a91611a8c84611a4d565b611848565b90508083825260208201905060208402830185811115611ab457611ab3611a79565b5b835b81811015611afb57803567ffffffffffffffff811115611ad957611ad86117cd565b5b808601611ae689826118e5565b85526020850194505050602081019050611ab6565b5050509392505050565b600082601f830112611b1a57611b196117cd565b5b8135611b2a848260208601611a7e565b91505092915050565b600060208284031215611b4957611b486117c3565b5b600082013567ffffffffffffffff811115611b6757611b666117c8565b5b611b7384828501611b05565b91505092915050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b600081519050919050565b600082825260208201905092915050565b60005b83811015611be2578082015181840152602081019050611bc7565b60008484015250505050565b6000611bf982611ba8565b611c038185611bb3565b9350611c13818560208601611bc4565b611c1c816117d7565b840191505092915050565b60006060830160008301518482036000860152611c448282611bee565b91505060208301518482036020860152611c5e8282611bee565b91505060408301518482036040860152611c788282611bee565b9150508091505092915050565b6000611c918383611c27565b905092915050565b6000602082019050919050565b6000611cb182611b7c565b611cbb8185611b87565b935083602082028501611ccd85611b98565b8060005b85811015611d095784840389528151611cea8582611c85565b9450611cf583611c99565b925060208a01995050600181019050611cd1565b50829750879550505050505092915050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b60008115159050919050565b611d5c81611d47565b82525050565b6000611d6e8383611d53565b60208301905092915050565b6000602082019050919050565b6000611d9282611d1b565b611d9c8185611d26565b9350611da783611d37565b8060005b83811015611dd8578151611dbf8882611d62565b9750611dca83611d7a565b925050600181019050611dab565b5085935050505092915050565b60006040820190508181036000830152611dff8185611ca6565b90508181036020830152611e138184611d87565b90509392505050565b611e2581611785565b8114611e3057600080fd5b50565b600081359050611e4281611e1c565b92915050565b60008060408385031215611e5f57611e5e6117c3565b5b6000611e6d85828601611e33565b9250506020611e7e85828601611e33565b9150509250929050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b6000611ec08383611bee565b905092915050565b6000602082019050919050565b6000611ee082611e88565b611eea8185611e93565b935083602082028501611efc85611ea4565b8060005b85811015611f385784840389528151611f198582611eb4565b9450611f2483611ec8565b925060208a01995050600181019050611f00565b50829750879550505050505092915050565b60006060820190508181036000830152611f648186611ed5565b90508181036020830152611f788185611ca6565b9050611f87604083018461178f565b949350505050565b600060208284031215611fa557611fa46117c3565b5b600082013567ffffffffffffffff811115611fc357611fc26117c8565b5b611fcf848285016118e5565b91505092915050565b611fe181611d47565b82525050565b6000602082019050611ffc6000830184611fd8565b92915050565b6000604082019050818103600083015261201c8185611ed5565b905061202b602083018461178f565b9392505050565b6000606083016000830151848203600086015261204f8282611bee565b915050602083015184820360208601526120698282611bee565b915050604083015184820360408601526120838282611bee565b9150508091505092915050565b600060408201905081810360008301526120aa8185612032565b90506120b96020830184611fd8565b9392505050565b600082825260208201905092915050565b7f4b65792063616e6e6f7420626520656d70747900000000000000000000000000600082015250565b60006121076013836120c0565b9150612112826120d1565b602082019050919050565b60006020820190508181036000830152612136816120fa565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600061217782611785565b915061218283611785565b925082820190508082111561219a5761219961213d565b5b92915050565b600081905092915050565b60006121b682611ba8565b6121c081856121a0565b93506121d0818560208601611bc4565b80840191505092915050565b60006121e882846121ab565b915081905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b6000600282049050600182168061223a57607f821691505b60208210810361224d5761224c6121f3565b5b50919050565b60008190508160005260206000209050919050565b60006020601f8301049050919050565b600082821b905092915050565b6000600883026122b57fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82612278565b6122bf8683612278565b95508019841693508086168417925050509392505050565b6000819050919050565b60006122fc6122f76122f284611785565b6122d7565b611785565b9050919050565b6000819050919050565b612316836122e1565b61232a61232282612303565b848454612285565b825550505050565b600090565b61233f612332565b61234a81848461230d565b505050565b5b8181101561236e57612363600082612337565b600181019050612350565b5050565b601f8211156123b35761238481612253565b61238d84612268565b8101602085101561239c578190505b6123b06123a885612268565b83018261234f565b50505b505050565b600082821c905092915050565b60006123d6600019846008026123b8565b1980831691505092915050565b60006123ef83836123c5565b9150826002028217905092915050565b61240882611ba8565b67ffffffffffffffff811115612421576124206117e8565b5b61242b8254612222565b612436828285612372565b600060209050601f8311600181146124695760008415612457578287015190505b61246185826123e3565b8655506124c9565b601f19841661247786612253565b60005b8281101561249f5784890151825560018201915060208501945060208101905061247a565b868310156124bc57848901516124b8601f8916826123c5565b8355505b6001600288020188555050505b505050505050565b60006124dc82611785565b91506124e783611785565b92508282039050818111156124ff576124fe61213d565b5b92915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4b657920646f6573206e6f742065786973740000000000000000000000000000600082015250565b600061256a6012836120c0565b915061257582612534565b602082019050919050565b600060208201905081810360008301526125998161255d565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fdfea26469706673582212206d7a7be588de9e5b02bffc80ea79dfdbc24ce443849bc498f8f3e36fe69acf0f64736f6c63430008180033" +const GenericStorageByteCodeStr = "60806040523480156200001157600080fd5b5033600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603620000885760006040517f1e4fbdf70000000000000000000000000000000000000000000000000000000081526004016200007f9190620001a9565b60405180910390fd5b6200009981620000a060201b60201c565b50620001c6565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050816000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000620001918262000164565b9050919050565b620001a38162000184565b82525050565b6000602082019050620001c0600083018462000198565b92915050565b6129ae80620001d66000396000f3fe608060405234801561001057600080fd5b50600436106100b45760003560e01c8063715018a611610071578063715018a61461017c57806379fc09a214610186578063821bef2f146101b65780638da5cb5b146101e7578063d6d7d52514610205578063f2fde38b14610236576100b4565b806306661abd146100b9578063072957b0146100d757806342e1ae2e146100f357806350fd73671461012457806352efea6e1461015657806358edef4c14610160575b600080fd5b6100c1610252565b6040516100ce91906117e7565b60405180910390f35b6100f160048036038101906100ec9190611a1e565b61025f565b005b61010d60048036038101906101089190611b7c565b61046e565b60405161011b929190611e2e565b60405180910390f35b61013e60048036038101906101399190611e91565b6107e1565b60405161014d93929190611f93565b60405180910390f35b61015e610c65565b005b61017a60048036038101906101759190611fd8565b610da3565b005b61018461104e565b005b6101a0600480360381019061019b9190611fd8565b611062565b6040516101ad9190612030565b60405180910390f35b6101d060048036038101906101cb9190611e91565b611074565b6040516101de92919061204b565b60405180910390f35b6101ef611243565b6040516101fc91906120bc565b60405180910390f35b61021f600480360381019061021a9190611fd8565b61126c565b60405161022d929190612135565b60405180910390f35b610250600480360381019061024b9190612191565b61149c565b005b6000600180549050905090565b610267611522565b60008251116102ab576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016102a29061221b565b60405180910390fd5b6102b4826115a9565b61039557600180805490506102c9919061226a565b6003836040516102d991906122da565b90815260200160405180910390208190555060018290806001815401808255809150506001900390600052602060002001600090919091909150908161031f91906124fd565b506002819080600181540180825580915050600190039060005260206000209060030201600090919091909150600082015181600001908161036191906124fd565b50602082015181600101908161037791906124fd565b50604082015181600201908161038d91906124fd565b505050610428565b80600260016003856040516103aa91906122da565b9081526020016040518091039020546103c391906125cf565b815481106103d4576103d3612603565b5b906000526020600020906003020160008201518160000190816103f791906124fd565b50602082015181600101908161040d91906124fd565b50604082015181600201908161042391906124fd565b509050505b8160405161043691906122da565b60405180910390207f281be1a469724e78f8c4152bcc9fb70a95646c3e1e2ade9293d8d497c976338a60405160405180910390a25050565b606080825167ffffffffffffffff81111561048c5761048b611831565b5b6040519080825280602002602001820160405280156104c557816020015b6104b26116a0565b8152602001906001900390816104aa5790505b509150825167ffffffffffffffff8111156104e3576104e2611831565b5b6040519080825280602002602001820160405280156105115781602001602082028036833780820191505090505b50905060005b83518110156107db5761054384828151811061053657610535612603565b5b60200260200101516115a9565b82828151811061055657610555612603565b5b60200260200101901515908115158152505081818151811061057b5761057a612603565b5b6020026020010151156107ce576002600160038684815181106105a1576105a0612603565b5b60200260200101516040516105b691906122da565b9081526020016040518091039020546105cf91906125cf565b815481106105e0576105df612603565b5b906000526020600020906003020160405180606001604052908160008201805461060990612320565b80601f016020809104026020016040519081016040528092919081815260200182805461063590612320565b80156106825780601f1061065757610100808354040283529160200191610682565b820191906000526020600020905b81548152906001019060200180831161066557829003601f168201915b5050505050815260200160018201805461069b90612320565b80601f01602080910402602001604051908101604052809291908181526020018280546106c790612320565b80156107145780601f106106e957610100808354040283529160200191610714565b820191906000526020600020905b8154815290600101906020018083116106f757829003601f168201915b5050505050815260200160028201805461072d90612320565b80601f016020809104026020016040519081016040528092919081815260200182805461075990612320565b80156107a65780601f1061077b576101008083540402835291602001916107a6565b820191906000526020600020905b81548152906001019060200180831161078957829003601f168201915b5050505050815250508382815181106107c2576107c1612603565b5b60200260200101819052505b8080600101915050610517565b50915091565b606080600060018054905090508085106108a257600067ffffffffffffffff8111156108105761080f611831565b5b60405190808252806020026020018201604052801561084357816020015b606081526020019060019003908161082e5790505b509250600067ffffffffffffffff81111561086157610860611831565b5b60405190808252806020026020018201604052801561089a57816020015b6108876116a0565b81526020019060019003908161087f5790505b509150610c5e565b600085826108b091906125cf565b905060008186116108c157856108c3565b815b90508067ffffffffffffffff8111156108df576108de611831565b5b60405190808252806020026020018201604052801561091257816020015b60608152602001906001900390816108fd5790505b5094508067ffffffffffffffff81111561092f5761092e611831565b5b60405190808252806020026020018201604052801561096857816020015b6109556116a0565b81526020019060019003908161094d5790505b50935060005b81811015610c5a5760008189610984919061226a565b90506001818154811061099a57610999612603565b5b9060005260206000200180546109af90612320565b80601f01602080910402602001604051908101604052809291908181526020018280546109db90612320565b8015610a285780601f106109fd57610100808354040283529160200191610a28565b820191906000526020600020905b815481529060010190602001808311610a0b57829003601f168201915b5050505050878381518110610a4057610a3f612603565b5b602002602001018190525060028181548110610a5f57610a5e612603565b5b9060005260206000209060030201604051806060016040529081600082018054610a8890612320565b80601f0160208091040260200160405190810160405280929190818152602001828054610ab490612320565b8015610b015780601f10610ad657610100808354040283529160200191610b01565b820191906000526020600020905b815481529060010190602001808311610ae457829003601f168201915b50505050508152602001600182018054610b1a90612320565b80601f0160208091040260200160405190810160405280929190818152602001828054610b4690612320565b8015610b935780601f10610b6857610100808354040283529160200191610b93565b820191906000526020600020905b815481529060010190602001808311610b7657829003601f168201915b50505050508152602001600282018054610bac90612320565b80601f0160208091040260200160405190810160405280929190818152602001828054610bd890612320565b8015610c255780601f10610bfa57610100808354040283529160200191610c25565b820191906000526020600020905b815481529060010190602001808311610c0857829003601f168201915b505050505081525050868381518110610c4157610c40612603565b5b602002602001018190525050808060010191505061096e565b5050505b9250925092565b610c6d611522565b60005b600180549050811015610d5857600060018281548110610c9357610c92612603565b5b906000526020600020018054610ca890612320565b80601f0160208091040260200160405190810160405280929190818152602001828054610cd490612320565b8015610d215780601f10610cf657610100808354040283529160200191610d21565b820191906000526020600020905b815481529060010190602001808311610d0457829003601f168201915b50505050509050600381604051610d3891906122da565b908152602001604051809103902060009055508080600101915050610c70565b5060016000610d6791906116c1565b60026000610d7591906116e2565b7f6c7e419df39ff46e811e7d979ebfd916b8d4960de06f479dc69cf8417cdb89e760405160405180910390a1565b610dab611522565b610db4816115a9565b610df3576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610dea9061267e565b60405180910390fd5b60006001600383604051610e0791906122da565b908152602001604051809103902054610e2091906125cf565b9050600060018080549050610e3591906125cf565b9050808214610f5a5760018181548110610e5257610e51612603565b5b9060005260206000200160018381548110610e7057610e6f612603565b5b906000526020600020019081610e8691906126c9565b5060028181548110610e9b57610e9a612603565b5b906000526020600020906003020160028381548110610ebd57610ebc612603565b5b906000526020600020906003020160008201816000019081610edf91906127c7565b5060018201816001019081610ef491906127c7565b5060028201816002019081610f0991906127c7565b50905050600182610f1a919061226a565b600360018381548110610f3057610f2f612603565b5b90600052602060002001604051610f479190612932565b9081526020016040518091039020819055505b6001805480610f6c57610f6b612949565b5b600190038181906000526020600020016000610f889190611706565b90556002805480610f9c57610f9b612949565b5b600190038181906000526020600020906003020160008082016000610fc19190611706565b600182016000610fd19190611706565b600282016000610fe19190611706565b50509055600383604051610ff591906122da565b9081526020016040518091039020600090558260405161101591906122da565b60405180910390207f9248955bf73fd007be0a0d9dc13c36f9e61c3642fbac04d8ac592e0c21d0103760405160405180910390a2505050565b611056611522565b61106060006115d4565b565b600061106d826115a9565b9050919050565b6060600060018054905090508084106110dd57600067ffffffffffffffff8111156110a2576110a1611831565b5b6040519080825280602002602001820160405280156110d557816020015b60608152602001906001900390816110c05790505b50915061123c565b600084826110eb91906125cf565b905060008185116110fc57846110fe565b815b90508067ffffffffffffffff81111561111a57611119611831565b5b60405190808252806020026020018201604052801561114d57816020015b60608152602001906001900390816111385790505b50935060005b818110156112385760018188611169919061226a565b8154811061117a57611179612603565b5b90600052602060002001805461118f90612320565b80601f01602080910402602001604051908101604052809291908181526020018280546111bb90612320565b80156112085780601f106111dd57610100808354040283529160200191611208565b820191906000526020600020905b8154815290600101906020018083116111eb57829003601f168201915b50505050508582815181106112205761121f612603565b5b60200260200101819052508080600101915050611153565b5050505b9250929050565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b6112746116a0565b600061127f836115a9565b90508015611497576002600160038560405161129b91906122da565b9081526020016040518091039020546112b491906125cf565b815481106112c5576112c4612603565b5b90600052602060002090600302016040518060600160405290816000820180546112ee90612320565b80601f016020809104026020016040519081016040528092919081815260200182805461131a90612320565b80156113675780601f1061133c57610100808354040283529160200191611367565b820191906000526020600020905b81548152906001019060200180831161134a57829003601f168201915b5050505050815260200160018201805461138090612320565b80601f01602080910402602001604051908101604052809291908181526020018280546113ac90612320565b80156113f95780601f106113ce576101008083540402835291602001916113f9565b820191906000526020600020905b8154815290600101906020018083116113dc57829003601f168201915b5050505050815260200160028201805461141290612320565b80601f016020809104026020016040519081016040528092919081815260200182805461143e90612320565b801561148b5780601f106114605761010080835404028352916020019161148b565b820191906000526020600020905b81548152906001019060200180831161146e57829003601f168201915b50505050508152505091505b915091565b6114a4611522565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036115165760006040517f1e4fbdf700000000000000000000000000000000000000000000000000000000815260040161150d91906120bc565b60405180910390fd5b61151f816115d4565b50565b61152a611698565b73ffffffffffffffffffffffffffffffffffffffff16611548611243565b73ffffffffffffffffffffffffffffffffffffffff16146115a75761156b611698565b6040517f118cdaa700000000000000000000000000000000000000000000000000000000815260040161159e91906120bc565b60405180910390fd5b565b6000806003836040516115bc91906122da565b90815260200160405180910390205414159050919050565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050816000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b600033905090565b60405180606001604052806060815260200160608152602001606081525090565b50805460008255906000526020600020908101906116df9190611746565b50565b5080546000825560030290600052602060002090810190611703919061176a565b50565b50805461171290612320565b6000825580601f106117245750611743565b601f01602090049060005260206000209081019061174291906117b1565b5b50565b5b80821115611766576000818161175d9190611706565b50600101611747565b5090565b5b808211156117ad57600080820160006117849190611706565b6001820160006117949190611706565b6002820160006117a49190611706565b5060030161176b565b5090565b5b808211156117ca5760008160009055506001016117b2565b5090565b6000819050919050565b6117e1816117ce565b82525050565b60006020820190506117fc60008301846117d8565b92915050565b6000604051905090565b600080fd5b600080fd5b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b61186982611820565b810181811067ffffffffffffffff8211171561188857611887611831565b5b80604052505050565b600061189b611802565b90506118a78282611860565b919050565b600067ffffffffffffffff8211156118c7576118c6611831565b5b6118d082611820565b9050602081019050919050565b82818337600083830152505050565b60006118ff6118fa846118ac565b611891565b90508281526020810184848401111561191b5761191a61181b565b5b6119268482856118dd565b509392505050565b600082601f83011261194357611942611816565b5b81356119538482602086016118ec565b91505092915050565b600080fd5b600080fd5b60006060828403121561197c5761197b61195c565b5b6119866060611891565b9050600082013567ffffffffffffffff8111156119a6576119a5611961565b5b6119b28482850161192e565b600083015250602082013567ffffffffffffffff8111156119d6576119d5611961565b5b6119e28482850161192e565b602083015250604082013567ffffffffffffffff811115611a0657611a05611961565b5b611a128482850161192e565b60408301525092915050565b60008060408385031215611a3557611a3461180c565b5b600083013567ffffffffffffffff811115611a5357611a52611811565b5b611a5f8582860161192e565b925050602083013567ffffffffffffffff811115611a8057611a7f611811565b5b611a8c85828601611966565b9150509250929050565b600067ffffffffffffffff821115611ab157611ab0611831565b5b602082029050602081019050919050565b600080fd5b6000611ada611ad584611a96565b611891565b90508083825260208201905060208402830185811115611afd57611afc611ac2565b5b835b81811015611b4457803567ffffffffffffffff811115611b2257611b21611816565b5b808601611b2f898261192e565b85526020850194505050602081019050611aff565b5050509392505050565b600082601f830112611b6357611b62611816565b5b8135611b73848260208601611ac7565b91505092915050565b600060208284031215611b9257611b9161180c565b5b600082013567ffffffffffffffff811115611bb057611baf611811565b5b611bbc84828501611b4e565b91505092915050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b600081519050919050565b600082825260208201905092915050565b60005b83811015611c2b578082015181840152602081019050611c10565b60008484015250505050565b6000611c4282611bf1565b611c4c8185611bfc565b9350611c5c818560208601611c0d565b611c6581611820565b840191505092915050565b60006060830160008301518482036000860152611c8d8282611c37565b91505060208301518482036020860152611ca78282611c37565b91505060408301518482036040860152611cc18282611c37565b9150508091505092915050565b6000611cda8383611c70565b905092915050565b6000602082019050919050565b6000611cfa82611bc5565b611d048185611bd0565b935083602082028501611d1685611be1565b8060005b85811015611d525784840389528151611d338582611cce565b9450611d3e83611ce2565b925060208a01995050600181019050611d1a565b50829750879550505050505092915050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b60008115159050919050565b611da581611d90565b82525050565b6000611db78383611d9c565b60208301905092915050565b6000602082019050919050565b6000611ddb82611d64565b611de58185611d6f565b9350611df083611d80565b8060005b83811015611e21578151611e088882611dab565b9750611e1383611dc3565b925050600181019050611df4565b5085935050505092915050565b60006040820190508181036000830152611e488185611cef565b90508181036020830152611e5c8184611dd0565b90509392505050565b611e6e816117ce565b8114611e7957600080fd5b50565b600081359050611e8b81611e65565b92915050565b60008060408385031215611ea857611ea761180c565b5b6000611eb685828601611e7c565b9250506020611ec785828601611e7c565b9150509250929050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b6000611f098383611c37565b905092915050565b6000602082019050919050565b6000611f2982611ed1565b611f338185611edc565b935083602082028501611f4585611eed565b8060005b85811015611f815784840389528151611f628582611efd565b9450611f6d83611f11565b925060208a01995050600181019050611f49565b50829750879550505050505092915050565b60006060820190508181036000830152611fad8186611f1e565b90508181036020830152611fc18185611cef565b9050611fd060408301846117d8565b949350505050565b600060208284031215611fee57611fed61180c565b5b600082013567ffffffffffffffff81111561200c5761200b611811565b5b6120188482850161192e565b91505092915050565b61202a81611d90565b82525050565b60006020820190506120456000830184612021565b92915050565b600060408201905081810360008301526120658185611f1e565b905061207460208301846117d8565b9392505050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006120a68261207b565b9050919050565b6120b68161209b565b82525050565b60006020820190506120d160008301846120ad565b92915050565b600060608301600083015184820360008601526120f48282611c37565b9150506020830151848203602086015261210e8282611c37565b915050604083015184820360408601526121288282611c37565b9150508091505092915050565b6000604082019050818103600083015261214f81856120d7565b905061215e6020830184612021565b9392505050565b61216e8161209b565b811461217957600080fd5b50565b60008135905061218b81612165565b92915050565b6000602082840312156121a7576121a661180c565b5b60006121b58482850161217c565b91505092915050565b600082825260208201905092915050565b7f4b65792063616e6e6f7420626520656d70747900000000000000000000000000600082015250565b60006122056013836121be565b9150612210826121cf565b602082019050919050565b60006020820190508181036000830152612234816121f8565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000612275826117ce565b9150612280836117ce565b92508282019050808211156122985761229761223b565b5b92915050565b600081905092915050565b60006122b482611bf1565b6122be818561229e565b93506122ce818560208601611c0d565b80840191505092915050565b60006122e682846122a9565b915081905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b6000600282049050600182168061233857607f821691505b60208210810361234b5761234a6122f1565b5b50919050565b60008190508160005260206000209050919050565b60006020601f8301049050919050565b600082821b905092915050565b6000600883026123b37fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82612376565b6123bd8683612376565b95508019841693508086168417925050509392505050565b6000819050919050565b60006123fa6123f56123f0846117ce565b6123d5565b6117ce565b9050919050565b6000819050919050565b612414836123df565b61242861242082612401565b848454612383565b825550505050565b600090565b61243d612430565b61244881848461240b565b505050565b5b8181101561246c57612461600082612435565b60018101905061244e565b5050565b601f8211156124b15761248281612351565b61248b84612366565b8101602085101561249a578190505b6124ae6124a685612366565b83018261244d565b50505b505050565b600082821c905092915050565b60006124d4600019846008026124b6565b1980831691505092915050565b60006124ed83836124c3565b9150826002028217905092915050565b61250682611bf1565b67ffffffffffffffff81111561251f5761251e611831565b5b6125298254612320565b612534828285612470565b600060209050601f8311600181146125675760008415612555578287015190505b61255f85826124e1565b8655506125c7565b601f19841661257586612351565b60005b8281101561259d57848901518255600182019150602085019450602081019050612578565b868310156125ba57848901516125b6601f8916826124c3565b8355505b6001600288020188555050505b505050505050565b60006125da826117ce565b91506125e5836117ce565b92508282039050818111156125fd576125fc61223b565b5b92915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4b657920646f6573206e6f742065786973740000000000000000000000000000600082015250565b60006126686012836121be565b915061267382612632565b602082019050919050565b600060208201905081810360008301526126978161265b565b9050919050565b6000815490506126ad81612320565b9050919050565b60008190508160005260206000209050919050565b8181036126d75750506127af565b6126e08261269e565b67ffffffffffffffff8111156126f9576126f8611831565b5b6127038254612320565b61270e828285612470565b6000601f83116001811461273d576000841561272b578287015490505b61273585826124e1565b8655506127a8565b601f19841661274b876126b4565b965061275686612351565b60005b8281101561277e57848901548255600182019150600185019450602081019050612759565b8683101561279b5784890154612797601f8916826124c3565b8355505b6001600288020188555050505b5050505050505b565b6000815490506127c081612320565b9050919050565b8181036127d55750506128ad565b6127de826127b1565b67ffffffffffffffff8111156127f7576127f6611831565b5b6128018254612320565b61280c828285612470565b6000601f83116001811461283b5760008415612829578287015490505b61283385826124e1565b8655506128a6565b601f19841661284987612351565b965061285486612351565b60005b8281101561287c57848901548255600182019150600185019450602081019050612857565b868310156128995784890154612895601f8916826124c3565b8355505b6001600288020188555050505b5050505050505b565b600081546128bc81612320565b6128c6818661229e565b945060018216600081146128e157600181146128f657612929565b60ff1983168652811515820286019350612929565b6128ff85612351565b60005b8381101561292157815481890152600182019150602081019050612902565b838801955050505b50505092915050565b600061293e82846128af565b915081905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fdfea2646970667358221220742757bbdebb67507bfe37b3bab5f5e531aad9896e9022a68c6faf2c49545c3564736f6c63430008180033" diff --git a/systemcontracts/namespace_storage.go b/systemcontracts/namespace_storage.go index 89b68f4476..909d542a61 100644 --- a/systemcontracts/namespace_storage.go +++ b/systemcontracts/namespace_storage.go @@ -98,6 +98,7 @@ func (ns *NamespaceStorageContract) Put(namespace string, key []byte, value Name // Execute the transaction callMsg := ðereum.CallMsg{ + From: common.BytesToAddress(systemContractCreatorAddr[:]), To: &ns.contractAddress, Data: data, Value: big.NewInt(0), @@ -133,6 +134,7 @@ func (ns *NamespaceStorageContract) Get(namespace string, key []byte) (*Namespac // Execute the call callMsg := ðereum.CallMsg{ + From: common.BytesToAddress(systemContractCreatorAddr[:]), To: &ns.contractAddress, Data: data, Value: big.NewInt(0), @@ -184,6 +186,7 @@ func (ns *NamespaceStorageContract) Remove(namespace string, key []byte) error { // Execute the transaction callMsg := ðereum.CallMsg{ + From: common.BytesToAddress(systemContractCreatorAddr[:]), To: &ns.contractAddress, Data: data, Value: big.NewInt(0), @@ -219,6 +222,7 @@ func (ns *NamespaceStorageContract) Exists(namespace string, key []byte) (bool, // Execute the call callMsg := ðereum.CallMsg{ + From: common.BytesToAddress(systemContractCreatorAddr[:]), To: &ns.contractAddress, Data: data, Value: big.NewInt(0), @@ -261,6 +265,7 @@ func (ns *NamespaceStorageContract) BatchGet(namespace string, keys [][]byte) (* // Execute the call callMsg := ðereum.CallMsg{ + From: common.BytesToAddress(systemContractCreatorAddr[:]), To: &ns.contractAddress, Data: data, Value: big.NewInt(0), @@ -314,6 +319,7 @@ func (ns *NamespaceStorageContract) BatchPut(namespace string, keys [][]byte, va // Execute the transaction callMsg := ðereum.CallMsg{ + From: common.BytesToAddress(systemContractCreatorAddr[:]), To: &ns.contractAddress, Data: data, Value: big.NewInt(0), @@ -352,6 +358,7 @@ func (ns *NamespaceStorageContract) List(namespace string, offset, limit *big.In // Execute the call callMsg := ðereum.CallMsg{ + From: common.BytesToAddress(systemContractCreatorAddr[:]), To: &ns.contractAddress, Data: data, Value: big.NewInt(0), @@ -407,6 +414,7 @@ func (ns *NamespaceStorageContract) ListKeys(namespace string, offset, limit *bi // Execute the call callMsg := ðereum.CallMsg{ + From: common.BytesToAddress(systemContractCreatorAddr[:]), To: &ns.contractAddress, Data: data, Value: big.NewInt(0), @@ -456,6 +464,7 @@ func (ns *NamespaceStorageContract) ListNamespaces(offset, limit *big.Int) (*Nam // Execute the call callMsg := ðereum.CallMsg{ + From: common.BytesToAddress(systemContractCreatorAddr[:]), To: &ns.contractAddress, Data: data, Value: big.NewInt(0), @@ -504,6 +513,7 @@ func (ns *NamespaceStorageContract) HasNamespace(namespace string) (bool, error) // Execute the call callMsg := ðereum.CallMsg{ + From: common.BytesToAddress(systemContractCreatorAddr[:]), To: &ns.contractAddress, Data: data, Value: big.NewInt(0), @@ -540,6 +550,7 @@ func (ns *NamespaceStorageContract) CountInNamespace(namespace string) (*big.Int // Execute the call callMsg := ðereum.CallMsg{ + From: common.BytesToAddress(systemContractCreatorAddr[:]), To: &ns.contractAddress, Data: data, Value: big.NewInt(0), @@ -571,6 +582,7 @@ func (ns *NamespaceStorageContract) NamespaceCount() (*big.Int, error) { // Execute the call callMsg := ðereum.CallMsg{ + From: common.BytesToAddress(systemContractCreatorAddr[:]), To: &ns.contractAddress, Data: data, Value: big.NewInt(0), @@ -602,6 +614,7 @@ func (ns *NamespaceStorageContract) TotalCount() (*big.Int, error) { // Execute the call callMsg := ðereum.CallMsg{ + From: common.BytesToAddress(systemContractCreatorAddr[:]), To: &ns.contractAddress, Data: data, Value: big.NewInt(0), @@ -638,6 +651,7 @@ func (ns *NamespaceStorageContract) ClearNamespace(namespace string) error { // Execute the transaction callMsg := ðereum.CallMsg{ + From: common.BytesToAddress(systemContractCreatorAddr[:]), To: &ns.contractAddress, Data: data, Value: big.NewInt(0), @@ -664,6 +678,7 @@ func (ns *NamespaceStorageContract) ClearAll() error { // Execute the transaction callMsg := ðereum.CallMsg{ + From: common.BytesToAddress(systemContractCreatorAddr[:]), To: &ns.contractAddress, Data: data, Value: big.NewInt(0), diff --git a/systemcontracts/namespace_storage_abi.go b/systemcontracts/namespace_storage_abi.go index 1d65ecea06..ddc2101fcf 100644 --- a/systemcontracts/namespace_storage_abi.go +++ b/systemcontracts/namespace_storage_abi.go @@ -2,505 +2,584 @@ package systemcontracts // NamespaceStorageABI is the ABI definition for the NamespaceStorage contract const NamespaceStorageABI = `[ - { - "anonymous": false, - "inputs": [], - "name": "AllDataCleared", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "string", - "name": "namespace", - "type": "string" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "keyCount", - "type": "uint256" - } - ], - "name": "BatchDataRetrieved", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "string", - "name": "namespace", - "type": "string" - }, - { - "indexed": true, - "internalType": "bytes", - "name": "key", - "type": "bytes" - } - ], - "name": "DataDeleted", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "string", - "name": "namespace", - "type": "string" - }, - { - "indexed": true, - "internalType": "bytes", - "name": "key", - "type": "bytes" - } - ], - "name": "DataStored", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "string", - "name": "namespace", - "type": "string" - } - ], - "name": "NamespaceCleared", - "type": "event" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "namespace", - "type": "string" - }, - { - "internalType": "bytes[]", - "name": "keyList", - "type": "bytes[]" - } - ], - "name": "batchGet", - "outputs": [ - { - "components": [ - { - "internalType": "bytes", - "name": "primaryData", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "secondaryData", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "auxiliaryData", - "type": "bytes" - } - ], - "internalType": "struct NamespaceStorage.GenericValue[]", - "name": "values", - "type": "tuple[]" - }, - { - "internalType": "bool[]", - "name": "existsFlags", - "type": "bool[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "namespace", - "type": "string" - }, - { - "internalType": "bytes[]", - "name": "keys", - "type": "bytes[]" - }, - { - "components": [ - { - "internalType": "bytes", - "name": "primaryData", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "secondaryData", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "auxiliaryData", - "type": "bytes" - } - ], - "internalType": "struct NamespaceStorage.GenericValue[]", - "name": "values", - "type": "tuple[]" - } - ], - "name": "batchPut", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "clearAll", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "namespace", - "type": "string" - } - ], - "name": "clearNamespace", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "namespace", - "type": "string" - } - ], - "name": "countInNamespace", - "outputs": [ - { - "internalType": "uint256", - "name": "itemCount", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "namespace", - "type": "string" - }, - { - "internalType": "bytes", - "name": "key", - "type": "bytes" - } - ], - "name": "exists", - "outputs": [ - { - "internalType": "bool", - "name": "keyExists", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "namespace", - "type": "string" - }, - { - "internalType": "bytes", - "name": "key", - "type": "bytes" - } - ], - "name": "get", - "outputs": [ - { - "components": [ - { - "internalType": "bytes", - "name": "primaryData", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "secondaryData", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "auxiliaryData", - "type": "bytes" - } - ], - "internalType": "struct NamespaceStorage.GenericValue", - "name": "value", - "type": "tuple" - }, - { - "internalType": "bool", - "name": "keyExists", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "namespace", - "type": "string" - } - ], - "name": "hasNamespace", - "outputs": [ - { - "internalType": "bool", - "name": "nsExists", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "namespace", - "type": "string" - }, - { - "internalType": "uint256", - "name": "offset", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "limit", - "type": "uint256" - } - ], - "name": "list", - "outputs": [ - { - "internalType": "bytes[]", - "name": "keyList", - "type": "bytes[]" - }, - { - "components": [ - { - "internalType": "bytes", - "name": "primaryData", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "secondaryData", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "auxiliaryData", - "type": "bytes" - } - ], - "internalType": "struct NamespaceStorage.GenericValue[]", - "name": "values", - "type": "tuple[]" - }, - { - "internalType": "uint256", - "name": "total", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "namespace", - "type": "string" - }, - { - "internalType": "uint256", - "name": "offset", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "limit", - "type": "uint256" - } - ], - "name": "listKeys", - "outputs": [ - { - "internalType": "bytes[]", - "name": "keyList", - "type": "bytes[]" - }, - { - "internalType": "uint256", - "name": "total", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "offset", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "limit", - "type": "uint256" - } - ], - "name": "listNamespaces", - "outputs": [ - { - "internalType": "string[]", - "name": "namespaceList", - "type": "string[]" - }, - { - "internalType": "uint256[]", - "name": "counts", - "type": "uint256[]" - }, - { - "internalType": "uint256", - "name": "total", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "namespaceCount", - "outputs": [ - { - "internalType": "uint256", - "name": "totalNamespaces", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "namespace", - "type": "string" - }, - { - "internalType": "bytes", - "name": "key", - "type": "bytes" - }, - { - "components": [ - { - "internalType": "bytes", - "name": "primaryData", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "secondaryData", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "auxiliaryData", - "type": "bytes" - } - ], - "internalType": "struct NamespaceStorage.GenericValue", - "name": "value", - "type": "tuple" - } - ], - "name": "put", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "namespace", - "type": "string" - }, - { - "internalType": "bytes", - "name": "key", - "type": "bytes" - } - ], - "name": "remove", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "totalCount", - "outputs": [ - { - "internalType": "uint256", - "name": "totalItems", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - } + { + "inputs": [], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "OwnableInvalidOwner", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "OwnableUnauthorizedAccount", + "type": "error" + }, + { + "anonymous": false, + "inputs": [], + "name": "AllDataCleared", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "string", + "name": "namespace", + "type": "string" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "keyCount", + "type": "uint256" + } + ], + "name": "BatchDataRetrieved", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "string", + "name": "namespace", + "type": "string" + }, + { + "indexed": true, + "internalType": "bytes", + "name": "key", + "type": "bytes" + } + ], + "name": "DataDeleted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "string", + "name": "namespace", + "type": "string" + }, + { + "indexed": true, + "internalType": "bytes", + "name": "key", + "type": "bytes" + } + ], + "name": "DataStored", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "string", + "name": "namespace", + "type": "string" + } + ], + "name": "NamespaceCleared", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "namespace", + "type": "string" + }, + { + "internalType": "bytes[]", + "name": "keyList", + "type": "bytes[]" + } + ], + "name": "batchGet", + "outputs": [ + { + "components": [ + { + "internalType": "bytes", + "name": "primaryData", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "secondaryData", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "auxiliaryData", + "type": "bytes" + } + ], + "internalType": "struct NamespaceStorage.GenericValue[]", + "name": "values", + "type": "tuple[]" + }, + { + "internalType": "bool[]", + "name": "existsFlags", + "type": "bool[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "namespace", + "type": "string" + }, + { + "internalType": "bytes[]", + "name": "keys", + "type": "bytes[]" + }, + { + "components": [ + { + "internalType": "bytes", + "name": "primaryData", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "secondaryData", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "auxiliaryData", + "type": "bytes" + } + ], + "internalType": "struct NamespaceStorage.GenericValue[]", + "name": "values", + "type": "tuple[]" + } + ], + "name": "batchPut", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "clearAll", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "namespace", + "type": "string" + } + ], + "name": "clearNamespace", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "namespace", + "type": "string" + } + ], + "name": "countInNamespace", + "outputs": [ + { + "internalType": "uint256", + "name": "itemCount", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "namespace", + "type": "string" + }, + { + "internalType": "bytes", + "name": "key", + "type": "bytes" + } + ], + "name": "exists", + "outputs": [ + { + "internalType": "bool", + "name": "keyExists", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "namespace", + "type": "string" + }, + { + "internalType": "bytes", + "name": "key", + "type": "bytes" + } + ], + "name": "get", + "outputs": [ + { + "components": [ + { + "internalType": "bytes", + "name": "primaryData", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "secondaryData", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "auxiliaryData", + "type": "bytes" + } + ], + "internalType": "struct NamespaceStorage.GenericValue", + "name": "value", + "type": "tuple" + }, + { + "internalType": "bool", + "name": "keyExists", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "namespace", + "type": "string" + } + ], + "name": "hasNamespace", + "outputs": [ + { + "internalType": "bool", + "name": "nsExists", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "namespace", + "type": "string" + }, + { + "internalType": "uint256", + "name": "offset", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "limit", + "type": "uint256" + } + ], + "name": "list", + "outputs": [ + { + "internalType": "bytes[]", + "name": "keyList", + "type": "bytes[]" + }, + { + "components": [ + { + "internalType": "bytes", + "name": "primaryData", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "secondaryData", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "auxiliaryData", + "type": "bytes" + } + ], + "internalType": "struct NamespaceStorage.GenericValue[]", + "name": "values", + "type": "tuple[]" + }, + { + "internalType": "uint256", + "name": "total", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "namespace", + "type": "string" + }, + { + "internalType": "uint256", + "name": "offset", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "limit", + "type": "uint256" + } + ], + "name": "listKeys", + "outputs": [ + { + "internalType": "bytes[]", + "name": "keyList", + "type": "bytes[]" + }, + { + "internalType": "uint256", + "name": "total", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "offset", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "limit", + "type": "uint256" + } + ], + "name": "listNamespaces", + "outputs": [ + { + "internalType": "string[]", + "name": "namespaceList", + "type": "string[]" + }, + { + "internalType": "uint256[]", + "name": "counts", + "type": "uint256[]" + }, + { + "internalType": "uint256", + "name": "total", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "namespaceCount", + "outputs": [ + { + "internalType": "uint256", + "name": "totalNamespaces", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "namespace", + "type": "string" + }, + { + "internalType": "bytes", + "name": "key", + "type": "bytes" + }, + { + "components": [ + { + "internalType": "bytes", + "name": "primaryData", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "secondaryData", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "auxiliaryData", + "type": "bytes" + } + ], + "internalType": "struct NamespaceStorage.GenericValue", + "name": "value", + "type": "tuple" + } + ], + "name": "put", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "namespace", + "type": "string" + }, + { + "internalType": "bytes", + "name": "key", + "type": "bytes" + } + ], + "name": "remove", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "totalCount", + "outputs": [ + { + "internalType": "uint256", + "name": "totalItems", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } ]` // NamespaceStorageContractByteCodeStr is the bytecode for the NamespaceStorage contract -const NamespaceStorageContractByteCodeStr = "608060405234801561001057600080fd5b50614122806100206000396000f3fe608060405234801561001057600080fd5b50600436106100f55760003560e01c8063912f309511610097578063c9037d2d11610066578063c9037d2d146102b1578063d1e96865146102e1578063ebb689a114610311578063f53504231461031b576100f5565b8063912f309514610214578063a2bc7a1c14610246578063aff6274514610262578063b40ec02b14610293576100f5565b80634b6b9a8c116100d35780634b6b9a8c146101655780634e8bfabb1461019657806353df2b27146101b257806370eafd18146101e4576100f5565b806304e52369146100fa57806312862f7f1461011657806334eafb1114610147575b600080fd5b610114600480360381019061010f9190612b91565b610337565b005b610130600480360381019061012b9190612cef565b6109b1565b60405161013e929190612fd0565b60405180910390f35b61014f610d65565b60405161015c9190613020565b60405180910390f35b61017f600480360381019061017a9190613067565b610dd7565b60405161018d929190613198565b60405180910390f35b6101b060048036038101906101ab919061336b565b610fc8565b005b6101cc60048036038101906101c79190613412565b6114a5565b6040516101db93929190613627565b60405180910390f35b6101fe60048036038101906101f9919061366c565b611753565b60405161020b91906136c4565b60405180910390f35b61022e60048036038101906102299190613067565b611788565b60405161023d939291906136df565b60405180910390f35b610260600480360381019061025b919061366c565b611c4b565b005b61027c60048036038101906102779190612b91565b611e77565b60405161028a929190613782565b60405180910390f35b61029b6120e8565b6040516102a89190613020565b60405180910390f35b6102cb60048036038101906102c6919061366c565b6120f5565b6040516102d89190613020565b60405180910390f35b6102fb60048036038101906102f69190612b91565b61211f565b60405161030891906136c4565b60405180910390f35b610319612133565b005b610335600480360381019061033091906137b2565b6123ec565b005b6004826040516103479190613895565b908152602001604051809103902060009054906101000a900460ff166103a2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161039990613909565b60405180910390fd5b6103ac828261279b565b6103eb576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103e290613975565b60405180910390fd5b600060016002846040516103ff9190613895565b90815260200160405180910390208360405161041b91906139d1565b9081526020016040518091039020546104349190613a17565b90506000600160008560405161044a9190613895565b9081526020016040518091039020805490506104669190613a17565b905080821461085257600080856040516104809190613895565b908152602001604051809103902082815481106104a05761049f613a4b565b5b9060005260206000200180546104b590613aa9565b80601f01602080910402602001604051908101604052809291908181526020018280546104e190613aa9565b801561052e5780601f106105035761010080835404028352916020019161052e565b820191906000526020600020905b81548152906001019060200180831161051157829003601f168201915b5050505050905060006001866040516105479190613895565b9081526020016040518091039020838154811061056757610566613a4b565b5b906000526020600020906003020160405180606001604052908160008201805461059090613aa9565b80601f01602080910402602001604051908101604052809291908181526020018280546105bc90613aa9565b80156106095780601f106105de57610100808354040283529160200191610609565b820191906000526020600020905b8154815290600101906020018083116105ec57829003601f168201915b5050505050815260200160018201805461062290613aa9565b80601f016020809104026020016040519081016040528092919081815260200182805461064e90613aa9565b801561069b5780601f106106705761010080835404028352916020019161069b565b820191906000526020600020905b81548152906001019060200180831161067e57829003601f168201915b505050505081526020016002820180546106b490613aa9565b80601f01602080910402602001604051908101604052809291908181526020018280546106e090613aa9565b801561072d5780601f106107025761010080835404028352916020019161072d565b820191906000526020600020905b81548152906001019060200180831161071057829003601f168201915b5050505050815250509050816000876040516107499190613895565b9081526020016040518091039020858154811061076957610768613a4b565b5b90600052602060002001908161077f9190613c86565b50806001876040516107919190613895565b908152602001604051809103902085815481106107b1576107b0613a4b565b5b906000526020600020906003020160008201518160000190816107d49190613c86565b5060208201518160010190816107ea9190613c86565b5060408201518160020190816108009190613c86565b509050506001846108119190613d58565b6002876040516108219190613895565b90815260200160405180910390208360405161083d91906139d1565b90815260200160405180910390208190555050505b6000846040516108629190613895565b90815260200160405180910390208054806108805761087f613d8c565b5b60019003818190600052602060002001600061089c91906127e3565b90556001846040516108ae9190613895565b90815260200160405180910390208054806108cc576108cb613d8c565b5b6001900381819060005260206000209060030201600080820160006108f191906127e3565b60018201600061090191906127e3565b60028201600061091191906127e3565b505090556002846040516109259190613895565b90815260200160405180910390208360405161094191906139d1565b9081526020016040518091039020600090558260405161096191906139d1565b6040518091039020846040516109779190613895565b60405180910390207faf8967c7b21227d5d987c31cd064433b027cf5bd93330cdbe6b62909093c417260405160405180910390a350505050565b606080825167ffffffffffffffff8111156109cf576109ce6129c5565b5b604051908082528060200260200182016040528015610a0857816020015b6109f5612823565b8152602001906001900390816109ed5790505b509150825167ffffffffffffffff811115610a2657610a256129c5565b5b604051908082528060200260200182016040528015610a545781602001602082028036833780820191505090505b50905060005b8351811015610d5d57610a8785858381518110610a7a57610a79613a4b565b5b602002602001015161279b565b828281518110610a9a57610a99613a4b565b5b602002602001019015159081151581525050818181518110610abf57610abe613a4b565b5b602002602001015115610d505760006001600287604051610ae09190613895565b9081526020016040518091039020868481518110610b0157610b00613a4b565b5b6020026020010151604051610b1691906139d1565b908152602001604051809103902054610b2f9190613a17565b9050600186604051610b419190613895565b90815260200160405180910390208181548110610b6157610b60613a4b565b5b9060005260206000209060030201604051806060016040529081600082018054610b8a90613aa9565b80601f0160208091040260200160405190810160405280929190818152602001828054610bb690613aa9565b8015610c035780601f10610bd857610100808354040283529160200191610c03565b820191906000526020600020905b815481529060010190602001808311610be657829003601f168201915b50505050508152602001600182018054610c1c90613aa9565b80601f0160208091040260200160405190810160405280929190818152602001828054610c4890613aa9565b8015610c955780601f10610c6a57610100808354040283529160200191610c95565b820191906000526020600020905b815481529060010190602001808311610c7857829003601f168201915b50505050508152602001600282018054610cae90613aa9565b80601f0160208091040260200160405190810160405280929190818152602001828054610cda90613aa9565b8015610d275780601f10610cfc57610100808354040283529160200191610d27565b820191906000526020600020905b815481529060010190602001808311610d0a57829003601f168201915b505050505081525050848381518110610d4357610d42613a4b565b5b6020026020010181905250505b8080600101915050610a5a565b509250929050565b600080600090505b600380549050811015610dd357600060038281548110610d9057610d8f613a4b565b5b90600052602060002001604051610da79190613e53565b90815260200160405180910390208054905082610dc49190613d58565b91508080600101915050610d6d565b5090565b6060600080600086604051610dec9190613895565b9081526020016040518091039020905080805490509150818510610e6157600067ffffffffffffffff811115610e2557610e246129c5565b5b604051908082528060200260200182016040528015610e5857816020015b6060815260200190600190039081610e435790505b50925050610fc0565b60008583610e6f9190613a17565b90506000818611610e805785610e82565b815b90508067ffffffffffffffff811115610e9e57610e9d6129c5565b5b604051908082528060200260200182016040528015610ed157816020015b6060815260200190600190039081610ebc5790505b50945060005b81811015610fbb57838189610eec9190613d58565b81548110610efd57610efc613a4b565b5b906000526020600020018054610f1290613aa9565b80601f0160208091040260200160405190810160405280929190818152602001828054610f3e90613aa9565b8015610f8b5780601f10610f6057610100808354040283529160200191610f8b565b820191906000526020600020905b815481529060010190602001808311610f6e57829003601f168201915b5050505050868281518110610fa357610fa2613a4b565b5b60200260200101819052508080600101915050610ed7565b505050505b935093915050565b805182511461100c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161100390613edc565b60405180910390fd5b6000835111611050576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161104790613f48565b60405180910390fd5b6004836040516110609190613895565b908152602001604051809103902060009054906101000a900460ff166110ed576003839080600181540180825580915050600190039060005260206000200160009091909190915090816110b49190613fae565b5060016004846040516110c79190613895565b908152602001604051809103902060006101000a81548160ff0219169083151502179055505b60005b825181101561149f57600083828151811061110e5761110d613a4b565b5b60200260200101515111611157576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161114e906140cc565b60405180910390fd5b61117b8484838151811061116e5761116d613a4b565b5b602002602001015161279b565b61131b5760016000856040516111919190613895565b9081526020016040518091039020805490506111ad9190613d58565b6002856040516111bd9190613895565b90815260200160405180910390208483815181106111de576111dd613a4b565b5b60200260200101516040516111f391906139d1565b9081526020016040518091039020819055506000846040516112159190613895565b908152602001604051809103902083828151811061123657611235613a4b565b5b602002602001015190806001815401808255809150506001900390600052602060002001600090919091909150908161126f9190613c86565b506001846040516112809190613895565b90815260200160405180910390208282815181106112a1576112a0613a4b565b5b6020026020010151908060018154018082558091505060019003906000526020600020906003020160009091909190915060008201518160000190816112e79190613c86565b5060208201518160010190816112fd9190613c86565b5060408201518160020190816113139190613c86565b505050611420565b6000600160028660405161132f9190613895565b90815260200160405180910390208584815181106113505761134f613a4b565b5b602002602001015160405161136591906139d1565b90815260200160405180910390205461137e9190613a17565b905082828151811061139357611392613a4b565b5b60200260200101516001866040516113ab9190613895565b908152602001604051809103902082815481106113cb576113ca613a4b565b5b906000526020600020906003020160008201518160000190816113ee9190613c86565b5060208201518160010190816114049190613c86565b50604082015181600201908161141a9190613c86565b50905050505b82818151811061143357611432613a4b565b5b602002602001015160405161144891906139d1565b60405180910390208460405161145e9190613895565b60405180910390207fd00871f87cd1b1b4e50e5be511f060478c06a013856673c392f2adbfa65df8ad60405160405180910390a380806001019150506110f0565b50505050565b6060806000600380549050905080851061155b57600067ffffffffffffffff8111156114d4576114d36129c5565b5b60405190808252806020026020018201604052801561150757816020015b60608152602001906001900390816114f25790505b509250600067ffffffffffffffff811115611525576115246129c5565b5b6040519080825280602002602001820160405280156115535781602001602082028036833780820191505090505b50915061174c565b600085826115699190613a17565b9050600081861161157a578561157c565b815b90508067ffffffffffffffff811115611598576115976129c5565b5b6040519080825280602002602001820160405280156115cb57816020015b60608152602001906001900390816115b65790505b5094508067ffffffffffffffff8111156115e8576115e76129c5565b5b6040519080825280602002602001820160405280156116165781602001602082028036833780820191505090505b50935060005b818110156117485760006003828a6116349190613d58565b8154811061164557611644613a4b565b5b90600052602060002001805461165a90613aa9565b80601f016020809104026020016040519081016040528092919081815260200182805461168690613aa9565b80156116d35780601f106116a8576101008083540402835291602001916116d3565b820191906000526020600020905b8154815290600101906020018083116116b657829003601f168201915b50505050509050808783815181106116ee576116ed613a4b565b5b60200260200101819052506000816040516117099190613895565b90815260200160405180910390208054905086838151811061172e5761172d613a4b565b5b60200260200101818152505050808060010191505061161c565b5050505b9250925092565b60006004826040516117659190613895565b908152602001604051809103902060009054906101000a900460ff169050919050565b60608060008060008760405161179e9190613895565b908152602001604051809103902090508080549050915081861061186a57600067ffffffffffffffff8111156117d7576117d66129c5565b5b60405190808252806020026020018201604052801561180a57816020015b60608152602001906001900390816117f55790505b509350600067ffffffffffffffff811115611828576118276129c5565b5b60405190808252806020026020018201604052801561186157816020015b61184e612823565b8152602001906001900390816118465790505b50925050611c42565b600086836118789190613a17565b90506000818711611889578661188b565b815b90508067ffffffffffffffff8111156118a7576118a66129c5565b5b6040519080825280602002602001820160405280156118da57816020015b60608152602001906001900390816118c55790505b5095508067ffffffffffffffff8111156118f7576118f66129c5565b5b60405190808252806020026020018201604052801561193057816020015b61191d612823565b8152602001906001900390816119155790505b50945060005b81811015611c3d576000818a61194c9190613d58565b905084818154811061196157611960613a4b565b5b90600052602060002001805461197690613aa9565b80601f01602080910402602001604051908101604052809291908181526020018280546119a290613aa9565b80156119ef5780601f106119c4576101008083540402835291602001916119ef565b820191906000526020600020905b8154815290600101906020018083116119d257829003601f168201915b5050505050888381518110611a0757611a06613a4b565b5b602002602001018190525060018b604051611a229190613895565b90815260200160405180910390208181548110611a4257611a41613a4b565b5b9060005260206000209060030201604051806060016040529081600082018054611a6b90613aa9565b80601f0160208091040260200160405190810160405280929190818152602001828054611a9790613aa9565b8015611ae45780601f10611ab957610100808354040283529160200191611ae4565b820191906000526020600020905b815481529060010190602001808311611ac757829003601f168201915b50505050508152602001600182018054611afd90613aa9565b80601f0160208091040260200160405190810160405280929190818152602001828054611b2990613aa9565b8015611b765780601f10611b4b57610100808354040283529160200191611b76565b820191906000526020600020905b815481529060010190602001808311611b5957829003601f168201915b50505050508152602001600282018054611b8f90613aa9565b80601f0160208091040260200160405190810160405280929190818152602001828054611bbb90613aa9565b8015611c085780601f10611bdd57610100808354040283529160200191611c08565b820191906000526020600020905b815481529060010190602001808311611beb57829003601f168201915b505050505081525050878381518110611c2457611c23613a4b565b5b6020026020010181905250508080600101915050611936565b505050505b93509350939050565b600481604051611c5b9190613895565b908152602001604051809103902060009054906101000a900460ff16611cb6576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611cad90613909565b60405180910390fd5b60008082604051611cc79190613895565b9081526020016040518091039020905060005b8180549050811015611ddc576000828281548110611cfb57611cfa613a4b565b5b906000526020600020018054611d1090613aa9565b80601f0160208091040260200160405190810160405280929190818152602001828054611d3c90613aa9565b8015611d895780601f10611d5e57610100808354040283529160200191611d89565b820191906000526020600020905b815481529060010190602001808311611d6c57829003601f168201915b50505050509050600284604051611da09190613895565b908152602001604051809103902081604051611dbc91906139d1565b908152602001604051809103902060009055508080600101915050611cda565b50600082604051611ded9190613895565b90815260200160405180910390206000611e079190612844565b600182604051611e179190613895565b90815260200160405180910390206000611e319190612865565b81604051611e3f9190613895565b60405180910390207f372dd188f66e03080f62fc207ebf4954a98c81128ca2472aedfc273f0f7c788360405160405180910390a25050565b611e7f612823565b6000611e8b848461279b565b905080156120e15760006001600286604051611ea79190613895565b908152602001604051809103902085604051611ec391906139d1565b908152602001604051809103902054611edc9190613a17565b9050600185604051611eee9190613895565b90815260200160405180910390208181548110611f0e57611f0d613a4b565b5b9060005260206000209060030201604051806060016040529081600082018054611f3790613aa9565b80601f0160208091040260200160405190810160405280929190818152602001828054611f6390613aa9565b8015611fb05780601f10611f8557610100808354040283529160200191611fb0565b820191906000526020600020905b815481529060010190602001808311611f9357829003601f168201915b50505050508152602001600182018054611fc990613aa9565b80601f0160208091040260200160405190810160405280929190818152602001828054611ff590613aa9565b80156120425780601f1061201757610100808354040283529160200191612042565b820191906000526020600020905b81548152906001019060200180831161202557829003601f168201915b5050505050815260200160028201805461205b90613aa9565b80601f016020809104026020016040519081016040528092919081815260200182805461208790613aa9565b80156120d45780601f106120a9576101008083540402835291602001916120d4565b820191906000526020600020905b8154815290600101906020018083116120b757829003601f168201915b5050505050815250509250505b9250929050565b6000600380549050905090565b600080826040516121069190613895565b9081526020016040518091039020805490509050919050565b600061212b838361279b565b905092915050565b60005b6003805490508110156123af5760006003828154811061215957612158613a4b565b5b90600052602060002001805461216e90613aa9565b80601f016020809104026020016040519081016040528092919081815260200182805461219a90613aa9565b80156121e75780601f106121bc576101008083540402835291602001916121e7565b820191906000526020600020905b8154815290600101906020018083116121ca57829003601f168201915b50505050509050600080826040516121ff9190613895565b9081526020016040518091039020905060005b818054905081101561231457600082828154811061223357612232613a4b565b5b90600052602060002001805461224890613aa9565b80601f016020809104026020016040519081016040528092919081815260200182805461227490613aa9565b80156122c15780601f10612296576101008083540402835291602001916122c1565b820191906000526020600020905b8154815290600101906020018083116122a457829003601f168201915b505050505090506002846040516122d89190613895565b9081526020016040518091039020816040516122f491906139d1565b908152602001604051809103902060009055508080600101915050612212565b506000826040516123259190613895565b9081526020016040518091039020600061233f9190612844565b60018260405161234f9190613895565b908152602001604051809103902060006123699190612865565b600060048360405161237b9190613895565b908152602001604051809103902060006101000a81548160ff02191690831515021790555050508080600101915050612136565b50600360006123be9190612889565b7f30addec5e9e954699f286bae8e1558655b0d436c3d7b501014eb5c0b4a76e6db60405160405180910390a1565b6000835111612430576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161242790613f48565b60405180910390fd5b6000825111612474576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161246b906140cc565b60405180910390fd5b6004836040516124849190613895565b908152602001604051809103902060009054906101000a900460ff16612511576003839080600181540180825580915050600190039060005260206000200160009091909190915090816124d89190613fae565b5060016004846040516124eb9190613895565b908152602001604051809103902060006101000a81548160ff0219169083151502179055505b61251b838361279b565b61266d5760016000846040516125319190613895565b90815260200160405180910390208054905061254d9190613d58565b60028460405161255d9190613895565b90815260200160405180910390208360405161257991906139d1565b90815260200160405180910390208190555060008360405161259b9190613895565b9081526020016040518091039020829080600181540180825580915050600190039060005260206000200160009091909190915090816125db9190613c86565b506001836040516125ec9190613895565b908152602001604051809103902081908060018154018082558091505060019003906000526020600020906003020160009091909190915060008201518160000190816126399190613c86565b50602082015181600101908161264f9190613c86565b5060408201518160020190816126659190613c86565b50505061273e565b600060016002856040516126819190613895565b90815260200160405180910390208460405161269d91906139d1565b9081526020016040518091039020546126b69190613a17565b9050816001856040516126c99190613895565b908152602001604051809103902082815481106126e9576126e8613a4b565b5b9060005260206000209060030201600082015181600001908161270c9190613c86565b5060208201518160010190816127229190613c86565b5060408201518160020190816127389190613c86565b50905050505b8160405161274c91906139d1565b6040518091039020836040516127629190613895565b60405180910390207fd00871f87cd1b1b4e50e5be511f060478c06a013856673c392f2adbfa65df8ad60405160405180910390a3505050565b6000806002846040516127ae9190613895565b9081526020016040518091039020836040516127ca91906139d1565b9081526020016040518091039020541415905092915050565b5080546127ef90613aa9565b6000825580601f106128015750612820565b601f01602090049060005260206000209081019061281f91906128aa565b5b50565b60405180606001604052806060815260200160608152602001606081525090565b508054600082559060005260206000209081019061286291906128c7565b50565b508054600082556003029060005260206000209081019061288691906128eb565b50565b50805460008255906000526020600020908101906128a79190612932565b50565b5b808211156128c35760008160009055506001016128ab565b5090565b5b808211156128e757600081816128de91906127e3565b506001016128c8565b5090565b5b8082111561292e576000808201600061290591906127e3565b60018201600061291591906127e3565b60028201600061292591906127e3565b506003016128ec565b5090565b5b8082111561295257600081816129499190612956565b50600101612933565b5090565b50805461296290613aa9565b6000825580601f106129745750612993565b601f01602090049060005260206000209081019061299291906128aa565b5b50565b6000604051905090565b600080fd5b600080fd5b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6129fd826129b4565b810181811067ffffffffffffffff82111715612a1c57612a1b6129c5565b5b80604052505050565b6000612a2f612996565b9050612a3b82826129f4565b919050565b600067ffffffffffffffff821115612a5b57612a5a6129c5565b5b612a64826129b4565b9050602081019050919050565b82818337600083830152505050565b6000612a93612a8e84612a40565b612a25565b905082815260208101848484011115612aaf57612aae6129af565b5b612aba848285612a71565b509392505050565b600082601f830112612ad757612ad66129aa565b5b8135612ae7848260208601612a80565b91505092915050565b600067ffffffffffffffff821115612b0b57612b0a6129c5565b5b612b14826129b4565b9050602081019050919050565b6000612b34612b2f84612af0565b612a25565b905082815260208101848484011115612b5057612b4f6129af565b5b612b5b848285612a71565b509392505050565b600082601f830112612b7857612b776129aa565b5b8135612b88848260208601612b21565b91505092915050565b60008060408385031215612ba857612ba76129a0565b5b600083013567ffffffffffffffff811115612bc657612bc56129a5565b5b612bd285828601612ac2565b925050602083013567ffffffffffffffff811115612bf357612bf26129a5565b5b612bff85828601612b63565b9150509250929050565b600067ffffffffffffffff821115612c2457612c236129c5565b5b602082029050602081019050919050565b600080fd5b6000612c4d612c4884612c09565b612a25565b90508083825260208201905060208402830185811115612c7057612c6f612c35565b5b835b81811015612cb757803567ffffffffffffffff811115612c9557612c946129aa565b5b808601612ca28982612b63565b85526020850194505050602081019050612c72565b5050509392505050565b600082601f830112612cd657612cd56129aa565b5b8135612ce6848260208601612c3a565b91505092915050565b60008060408385031215612d0657612d056129a0565b5b600083013567ffffffffffffffff811115612d2457612d236129a5565b5b612d3085828601612ac2565b925050602083013567ffffffffffffffff811115612d5157612d506129a5565b5b612d5d85828601612cc1565b9150509250929050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b600081519050919050565b600082825260208201905092915050565b60005b83811015612dcd578082015181840152602081019050612db2565b60008484015250505050565b6000612de482612d93565b612dee8185612d9e565b9350612dfe818560208601612daf565b612e07816129b4565b840191505092915050565b60006060830160008301518482036000860152612e2f8282612dd9565b91505060208301518482036020860152612e498282612dd9565b91505060408301518482036040860152612e638282612dd9565b9150508091505092915050565b6000612e7c8383612e12565b905092915050565b6000602082019050919050565b6000612e9c82612d67565b612ea68185612d72565b935083602082028501612eb885612d83565b8060005b85811015612ef45784840389528151612ed58582612e70565b9450612ee083612e84565b925060208a01995050600181019050612ebc565b50829750879550505050505092915050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b60008115159050919050565b612f4781612f32565b82525050565b6000612f598383612f3e565b60208301905092915050565b6000602082019050919050565b6000612f7d82612f06565b612f878185612f11565b9350612f9283612f22565b8060005b83811015612fc3578151612faa8882612f4d565b9750612fb583612f65565b925050600181019050612f96565b5085935050505092915050565b60006040820190508181036000830152612fea8185612e91565b90508181036020830152612ffe8184612f72565b90509392505050565b6000819050919050565b61301a81613007565b82525050565b60006020820190506130356000830184613011565b92915050565b61304481613007565b811461304f57600080fd5b50565b6000813590506130618161303b565b92915050565b6000806000606084860312156130805761307f6129a0565b5b600084013567ffffffffffffffff81111561309e5761309d6129a5565b5b6130aa86828701612ac2565b93505060206130bb86828701613052565b92505060406130cc86828701613052565b9150509250925092565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b600061310e8383612dd9565b905092915050565b6000602082019050919050565b600061312e826130d6565b61313881856130e1565b93508360208202850161314a856130f2565b8060005b8581101561318657848403895281516131678582613102565b945061317283613116565b925060208a0199505060018101905061314e565b50829750879550505050505092915050565b600060408201905081810360008301526131b28185613123565b90506131c16020830184613011565b9392505050565b600067ffffffffffffffff8211156131e3576131e26129c5565b5b602082029050602081019050919050565b600080fd5b600080fd5b600060608284031215613214576132136131f4565b5b61321e6060612a25565b9050600082013567ffffffffffffffff81111561323e5761323d6131f9565b5b61324a84828501612b63565b600083015250602082013567ffffffffffffffff81111561326e5761326d6131f9565b5b61327a84828501612b63565b602083015250604082013567ffffffffffffffff81111561329e5761329d6131f9565b5b6132aa84828501612b63565b60408301525092915050565b60006132c96132c4846131c8565b612a25565b905080838252602082019050602084028301858111156132ec576132eb612c35565b5b835b8181101561333357803567ffffffffffffffff811115613311576133106129aa565b5b80860161331e89826131fe565b855260208501945050506020810190506132ee565b5050509392505050565b600082601f830112613352576133516129aa565b5b81356133628482602086016132b6565b91505092915050565b600080600060608486031215613384576133836129a0565b5b600084013567ffffffffffffffff8111156133a2576133a16129a5565b5b6133ae86828701612ac2565b935050602084013567ffffffffffffffff8111156133cf576133ce6129a5565b5b6133db86828701612cc1565b925050604084013567ffffffffffffffff8111156133fc576133fb6129a5565b5b6134088682870161333d565b9150509250925092565b60008060408385031215613429576134286129a0565b5b600061343785828601613052565b925050602061344885828601613052565b9150509250929050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b600081519050919050565b600082825260208201905092915050565b60006134a58261347e565b6134af8185613489565b93506134bf818560208601612daf565b6134c8816129b4565b840191505092915050565b60006134df838361349a565b905092915050565b6000602082019050919050565b60006134ff82613452565b613509818561345d565b93508360208202850161351b8561346e565b8060005b85811015613557578484038952815161353885826134d3565b9450613543836134e7565b925060208a0199505060018101905061351f565b50829750879550505050505092915050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b61359e81613007565b82525050565b60006135b08383613595565b60208301905092915050565b6000602082019050919050565b60006135d482613569565b6135de8185613574565b93506135e983613585565b8060005b8381101561361a57815161360188826135a4565b975061360c836135bc565b9250506001810190506135ed565b5085935050505092915050565b6000606082019050818103600083015261364181866134f4565b9050818103602083015261365581856135c9565b90506136646040830184613011565b949350505050565b600060208284031215613682576136816129a0565b5b600082013567ffffffffffffffff8111156136a05761369f6129a5565b5b6136ac84828501612ac2565b91505092915050565b6136be81612f32565b82525050565b60006020820190506136d960008301846136b5565b92915050565b600060608201905081810360008301526136f98186613123565b9050818103602083015261370d8185612e91565b905061371c6040830184613011565b949350505050565b600060608301600083015184820360008601526137418282612dd9565b9150506020830151848203602086015261375b8282612dd9565b915050604083015184820360408601526137758282612dd9565b9150508091505092915050565b6000604082019050818103600083015261379c8185613724565b90506137ab60208301846136b5565b9392505050565b6000806000606084860312156137cb576137ca6129a0565b5b600084013567ffffffffffffffff8111156137e9576137e86129a5565b5b6137f586828701612ac2565b935050602084013567ffffffffffffffff811115613816576138156129a5565b5b61382286828701612b63565b925050604084013567ffffffffffffffff811115613843576138426129a5565b5b61384f868287016131fe565b9150509250925092565b600081905092915050565b600061386f8261347e565b6138798185613859565b9350613889818560208601612daf565b80840191505092915050565b60006138a18284613864565b915081905092915050565b600082825260208201905092915050565b7f4e616d65737061636520646f6573206e6f742065786973740000000000000000600082015250565b60006138f36018836138ac565b91506138fe826138bd565b602082019050919050565b60006020820190508181036000830152613922816138e6565b9050919050565b7f4b657920646f6573206e6f7420657869737420696e206e616d65737061636500600082015250565b600061395f601f836138ac565b915061396a82613929565b602082019050919050565b6000602082019050818103600083015261398e81613952565b9050919050565b600081905092915050565b60006139ab82612d93565b6139b58185613995565b93506139c5818560208601612daf565b80840191505092915050565b60006139dd82846139a0565b915081905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000613a2282613007565b9150613a2d83613007565b9250828203905081811115613a4557613a446139e8565b5b92915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b60006002820490506001821680613ac157607f821691505b602082108103613ad457613ad3613a7a565b5b50919050565b60008190508160005260206000209050919050565b60006020601f8301049050919050565b600082821b905092915050565b600060088302613b3c7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82613aff565b613b468683613aff565b95508019841693508086168417925050509392505050565b6000819050919050565b6000613b83613b7e613b7984613007565b613b5e565b613007565b9050919050565b6000819050919050565b613b9d83613b68565b613bb1613ba982613b8a565b848454613b0c565b825550505050565b600090565b613bc6613bb9565b613bd1818484613b94565b505050565b5b81811015613bf557613bea600082613bbe565b600181019050613bd7565b5050565b601f821115613c3a57613c0b81613ada565b613c1484613aef565b81016020851015613c23578190505b613c37613c2f85613aef565b830182613bd6565b50505b505050565b600082821c905092915050565b6000613c5d60001984600802613c3f565b1980831691505092915050565b6000613c768383613c4c565b9150826002028217905092915050565b613c8f82612d93565b67ffffffffffffffff811115613ca857613ca76129c5565b5b613cb28254613aa9565b613cbd828285613bf9565b600060209050601f831160018114613cf05760008415613cde578287015190505b613ce88582613c6a565b865550613d50565b601f198416613cfe86613ada565b60005b82811015613d2657848901518255600182019150602085019450602081019050613d01565b86831015613d435784890151613d3f601f891682613c4c565b8355505b6001600288020188555050505b505050505050565b6000613d6382613007565b9150613d6e83613007565b9250828201905080821115613d8657613d856139e8565b5b92915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b60008190508160005260206000209050919050565b60008154613ddd81613aa9565b613de78186613859565b94506001821660008114613e025760018114613e1757613e4a565b60ff1983168652811515820286019350613e4a565b613e2085613dbb565b60005b83811015613e4257815481890152600182019150602081019050613e23565b838801955050505b50505092915050565b6000613e5f8284613dd0565b915081905092915050565b7f4b65797320616e642076616c75657320617272617973206d757374206861766560008201527f2073616d65206c656e6774680000000000000000000000000000000000000000602082015250565b6000613ec6602c836138ac565b9150613ed182613e6a565b604082019050919050565b60006020820190508181036000830152613ef581613eb9565b9050919050565b7f4e616d6573706163652063616e6e6f7420626520656d70747900000000000000600082015250565b6000613f326019836138ac565b9150613f3d82613efc565b602082019050919050565b60006020820190508181036000830152613f6181613f25565b9050919050565b601f821115613fa957613f7a81613dbb565b613f8384613aef565b81016020851015613f92578190505b613fa6613f9e85613aef565b830182613bd6565b50505b505050565b613fb78261347e565b67ffffffffffffffff811115613fd057613fcf6129c5565b5b613fda8254613aa9565b613fe5828285613f68565b600060209050601f8311600181146140185760008415614006578287015190505b6140108582613c6a565b865550614078565b601f19841661402686613dbb565b60005b8281101561404e57848901518255600182019150602085019450602081019050614029565b8683101561406b5784890151614067601f891682613c4c565b8355505b6001600288020188555050505b505050505050565b7f4b65792063616e6e6f7420626520656d70747900000000000000000000000000600082015250565b60006140b66013836138ac565b91506140c182614080565b602082019050919050565b600060208201905081810360008301526140e5816140a9565b905091905056fea26469706673582212202ff7da17132a43f690d61f599721b55cc44e8324d1af1c4c5ca8ce4a4fe52e7664736f6c63430008180033" +const NamespaceStorageContractByteCodeStr = "60806040523480156200001157600080fd5b5033600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603620000885760006040517f1e4fbdf70000000000000000000000000000000000000000000000000000000081526004016200007f9190620001a9565b60405180910390fd5b6200009981620000a060201b60201c565b50620001c6565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050816000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000620001918262000164565b9050919050565b620001a38162000184565b82525050565b6000602082019050620001c0600083018462000198565b92915050565b6143f280620001d66000396000f3fe608060405234801561001057600080fd5b50600436106101165760003560e01c8063912f3095116100a2578063c9037d2d11610071578063c9037d2d146102fa578063d1e968651461032a578063ebb689a11461035a578063f2fde38b14610364578063f53504231461038057610116565b8063912f30951461025d578063a2bc7a1c1461028f578063aff62745146102ab578063b40ec02b146102dc57610116565b80634e8bfabb116100e95780634e8bfabb146101b757806353df2b27146101d357806370eafd1814610205578063715018a6146102355780638da5cb5b1461023f57610116565b806304e523691461011b57806312862f7f1461013757806334eafb11146101685780634b6b9a8c14610186575b600080fd5b61013560048036038101906101309190612b01565b61039c565b005b610151600480360381019061014c9190612c5f565b6107fe565b60405161015f929190612f40565b60405180910390f35b610170610bac565b60405161017d9190612f90565b60405180910390f35b6101a0600480360381019061019b9190612fd7565b610c1e565b6040516101ae929190613108565b60405180910390f35b6101d160048036038101906101cc91906132db565b610e0f565b005b6101ed60048036038101906101e89190613382565b6112ed565b6040516101fc93929190613597565b60405180910390f35b61021f600480360381019061021a91906135dc565b6115bd565b60405161022c9190613634565b60405180910390f35b61023d6115f2565b005b610247611606565b6040516102549190613690565b60405180910390f35b61027760048036038101906102729190612fd7565b61162f565b604051610286939291906136ab565b60405180910390f35b6102a960048036038101906102a491906135dc565b611af2565b005b6102c560048036038101906102c09190612b01565b611c98565b6040516102d392919061374e565b60405180910390f35b6102e4611f03565b6040516102f19190612f90565b60405180910390f35b610314600480360381019061030f91906135dc565b611f10565b6040516103219190612f90565b60405180910390f35b610344600480360381019061033f9190612b01565b611f3b565b6040516103519190613634565b60405180910390f35b610362611f4f565b005b61037e600480360381019061037991906137aa565b612182565b005b61039a600480360381019061039591906137d7565b612208565b005b6103a46125b8565b6005826040516103b491906138ba565b908152602001604051809103902060009054906101000a900460ff1661040f576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016104069061392e565b60405180910390fd5b610419828261263f565b610458576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161044f9061399a565b60405180910390fd5b6000600160038460405161046c91906138ba565b90815260200160405180910390208360405161048891906139f6565b9081526020016040518091039020546104a19190613a3c565b90506000600180856040516104b691906138ba565b9081526020016040518091039020805490506104d29190613a3c565b905080821461069f576001846040516104eb91906138ba565b9081526020016040518091039020818154811061050b5761050a613a70565b5b9060005260206000200160018560405161052591906138ba565b9081526020016040518091039020838154811061054557610544613a70565b5b90600052602060002001908161055b9190613cd6565b5060028460405161056c91906138ba565b9081526020016040518091039020818154811061058c5761058b613a70565b5b90600052602060002090600302016002856040516105aa91906138ba565b908152602001604051809103902083815481106105ca576105c9613a70565b5b9060005260206000209060030201600082018160000190816105ec9190613dd4565b50600182018160010190816106019190613dd4565b50600282018160020190816106169190613dd4565b509050506001826106279190613ebc565b60038560405161063791906138ba565b908152602001604051809103902060018660405161065591906138ba565b9081526020016040518091039020838154811061067557610674613a70565b5b9060005260206000200160405161068c9190613f73565b9081526020016040518091039020819055505b6001846040516106af91906138ba565b90815260200160405180910390208054806106cd576106cc613f8a565b5b6001900381819060005260206000200160006106e99190612753565b90556002846040516106fb91906138ba565b908152602001604051809103902080548061071957610718613f8a565b5b60019003818190600052602060002090600302016000808201600061073e9190612753565b60018201600061074e9190612753565b60028201600061075e9190612753565b5050905560038460405161077291906138ba565b90815260200160405180910390208360405161078e91906139f6565b908152602001604051809103902060009055826040516107ae91906139f6565b6040518091039020846040516107c491906138ba565b60405180910390207faf8967c7b21227d5d987c31cd064433b027cf5bd93330cdbe6b62909093c417260405160405180910390a350505050565b606080825167ffffffffffffffff81111561081c5761081b612935565b5b60405190808252806020026020018201604052801561085557816020015b610842612793565b81526020019060019003908161083a5790505b509150825167ffffffffffffffff81111561087357610872612935565b5b6040519080825280602002602001820160405280156108a15781602001602082028036833780820191505090505b50905060005b8351811015610ba4576108d4858583815181106108c7576108c6613a70565b5b602002602001015161263f565b8282815181106108e7576108e6613a70565b5b60200260200101901515908115158152505081818151811061090c5761090b613a70565b5b602002602001015115610b975760028560405161092991906138ba565b9081526020016040518091039020600160038760405161094991906138ba565b908152602001604051809103902086848151811061096a57610969613a70565b5b602002602001015160405161097f91906139f6565b9081526020016040518091039020546109989190613a3c565b815481106109a9576109a8613a70565b5b90600052602060002090600302016040518060600160405290816000820180546109d290613ace565b80601f01602080910402602001604051908101604052809291908181526020018280546109fe90613ace565b8015610a4b5780601f10610a2057610100808354040283529160200191610a4b565b820191906000526020600020905b815481529060010190602001808311610a2e57829003601f168201915b50505050508152602001600182018054610a6490613ace565b80601f0160208091040260200160405190810160405280929190818152602001828054610a9090613ace565b8015610add5780601f10610ab257610100808354040283529160200191610add565b820191906000526020600020905b815481529060010190602001808311610ac057829003601f168201915b50505050508152602001600282018054610af690613ace565b80601f0160208091040260200160405190810160405280929190818152602001828054610b2290613ace565b8015610b6f5780601f10610b4457610100808354040283529160200191610b6f565b820191906000526020600020905b815481529060010190602001808311610b5257829003601f168201915b505050505081525050838281518110610b8b57610b8a613a70565b5b60200260200101819052505b80806001019150506108a7565b509250929050565b600080600090505b600480549050811015610c1a57600160048281548110610bd757610bd6613a70565b5b90600052602060002001604051610bee9190614051565b90815260200160405180910390208054905082610c0b9190613ebc565b91508080600101915050610bb4565b5090565b6060600080600186604051610c3391906138ba565b9081526020016040518091039020905080805490509150818510610ca857600067ffffffffffffffff811115610c6c57610c6b612935565b5b604051908082528060200260200182016040528015610c9f57816020015b6060815260200190600190039081610c8a5790505b50925050610e07565b60008583610cb69190613a3c565b90506000818611610cc75785610cc9565b815b90508067ffffffffffffffff811115610ce557610ce4612935565b5b604051908082528060200260200182016040528015610d1857816020015b6060815260200190600190039081610d035790505b50945060005b81811015610e0257838189610d339190613ebc565b81548110610d4457610d43613a70565b5b906000526020600020018054610d5990613ace565b80601f0160208091040260200160405190810160405280929190818152602001828054610d8590613ace565b8015610dd25780601f10610da757610100808354040283529160200191610dd2565b820191906000526020600020905b815481529060010190602001808311610db557829003601f168201915b5050505050868281518110610dea57610de9613a70565b5b60200260200101819052508080600101915050610d1e565b505050505b935093915050565b610e176125b8565b8051825114610e5b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e52906140da565b60405180910390fd5b6000835111610e9f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e9690614146565b60405180910390fd5b600583604051610eaf91906138ba565b908152602001604051809103902060009054906101000a900460ff16610f3c57600483908060018154018082558091505060019003906000526020600020016000909190919091509081610f0391906141ac565b506001600584604051610f1691906138ba565b908152602001604051809103902060006101000a81548160ff0219169083151502179055505b60005b82518110156112e7576000838281518110610f5d57610f5c613a70565b5b60200260200101515111610fa6576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610f9d906142ca565b60405180910390fd5b610fca84848381518110610fbd57610fbc613a70565b5b602002602001015161263f565b6111695760018085604051610fdf91906138ba565b908152602001604051809103902080549050610ffb9190613ebc565b60038560405161100b91906138ba565b908152602001604051809103902084838151811061102c5761102b613a70565b5b602002602001015160405161104191906139f6565b90815260200160405180910390208190555060018460405161106391906138ba565b908152602001604051809103902083828151811061108457611083613a70565b5b60200260200101519080600181540180825580915050600190039060005260206000200160009091909190915090816110bd91906142ea565b506002846040516110ce91906138ba565b90815260200160405180910390208282815181106110ef576110ee613a70565b5b60200260200101519080600181540180825580915050600190039060005260206000209060030201600090919091909150600082015181600001908161113591906142ea565b50602082015181600101908161114b91906142ea565b50604082015181600201908161116191906142ea565b505050611268565b81818151811061117c5761117b613a70565b5b602002602001015160028560405161119491906138ba565b908152602001604051809103902060016003876040516111b491906138ba565b90815260200160405180910390208685815181106111d5576111d4613a70565b5b60200260200101516040516111ea91906139f6565b9081526020016040518091039020546112039190613a3c565b8154811061121457611213613a70565b5b9060005260206000209060030201600082015181600001908161123791906142ea565b50602082015181600101908161124d91906142ea565b50604082015181600201908161126391906142ea565b509050505b82818151811061127b5761127a613a70565b5b602002602001015160405161129091906139f6565b6040518091039020846040516112a691906138ba565b60405180910390207fd00871f87cd1b1b4e50e5be511f060478c06a013856673c392f2adbfa65df8ad60405160405180910390a38080600101915050610f3f565b50505050565b606080600060048054905090508085106113a357600067ffffffffffffffff81111561131c5761131b612935565b5b60405190808252806020026020018201604052801561134f57816020015b606081526020019060019003908161133a5790505b509250600067ffffffffffffffff81111561136d5761136c612935565b5b60405190808252806020026020018201604052801561139b5781602001602082028036833780820191505090505b5091506115b6565b600085826113b19190613a3c565b905060008186116113c257856113c4565b815b90508067ffffffffffffffff8111156113e0576113df612935565b5b60405190808252806020026020018201604052801561141357816020015b60608152602001906001900390816113fe5790505b5094508067ffffffffffffffff8111156114305761142f612935565b5b60405190808252806020026020018201604052801561145e5781602001602082028036833780820191505090505b50935060005b818110156115b2576004818961147a9190613ebc565b8154811061148b5761148a613a70565b5b9060005260206000200180546114a090613ace565b80601f01602080910402602001604051908101604052809291908181526020018280546114cc90613ace565b80156115195780601f106114ee57610100808354040283529160200191611519565b820191906000526020600020905b8154815290600101906020018083116114fc57829003601f168201915b505050505086828151811061153157611530613a70565b5b602002602001018190525060016004828a61154c9190613ebc565b8154811061155d5761155c613a70565b5b906000526020600020016040516115749190614051565b90815260200160405180910390208054905085828151811061159957611598613a70565b5b6020026020010181815250508080600101915050611464565b5050505b9250925092565b60006005826040516115cf91906138ba565b908152602001604051809103902060009054906101000a900460ff169050919050565b6115fa6125b8565b6116046000612687565b565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b60608060008060018760405161164591906138ba565b908152602001604051809103902090508080549050915081861061171157600067ffffffffffffffff81111561167e5761167d612935565b5b6040519080825280602002602001820160405280156116b157816020015b606081526020019060019003908161169c5790505b509350600067ffffffffffffffff8111156116cf576116ce612935565b5b60405190808252806020026020018201604052801561170857816020015b6116f5612793565b8152602001906001900390816116ed5790505b50925050611ae9565b6000868361171f9190613a3c565b905060008187116117305786611732565b815b90508067ffffffffffffffff81111561174e5761174d612935565b5b60405190808252806020026020018201604052801561178157816020015b606081526020019060019003908161176c5790505b5095508067ffffffffffffffff81111561179e5761179d612935565b5b6040519080825280602002602001820160405280156117d757816020015b6117c4612793565b8152602001906001900390816117bc5790505b50945060005b81811015611ae4576000818a6117f39190613ebc565b905084818154811061180857611807613a70565b5b90600052602060002001805461181d90613ace565b80601f016020809104026020016040519081016040528092919081815260200182805461184990613ace565b80156118965780601f1061186b57610100808354040283529160200191611896565b820191906000526020600020905b81548152906001019060200180831161187957829003601f168201915b50505050508883815181106118ae576118ad613a70565b5b602002602001018190525060028b6040516118c991906138ba565b908152602001604051809103902081815481106118e9576118e8613a70565b5b906000526020600020906003020160405180606001604052908160008201805461191290613ace565b80601f016020809104026020016040519081016040528092919081815260200182805461193e90613ace565b801561198b5780601f106119605761010080835404028352916020019161198b565b820191906000526020600020905b81548152906001019060200180831161196e57829003601f168201915b505050505081526020016001820180546119a490613ace565b80601f01602080910402602001604051908101604052809291908181526020018280546119d090613ace565b8015611a1d5780601f106119f257610100808354040283529160200191611a1d565b820191906000526020600020905b815481529060010190602001808311611a0057829003601f168201915b50505050508152602001600282018054611a3690613ace565b80601f0160208091040260200160405190810160405280929190818152602001828054611a6290613ace565b8015611aaf5780601f10611a8457610100808354040283529160200191611aaf565b820191906000526020600020905b815481529060010190602001808311611a9257829003601f168201915b505050505081525050878381518110611acb57611aca613a70565b5b60200260200101819052505080806001019150506117dd565b505050505b93509350939050565b611afa6125b8565b600581604051611b0a91906138ba565b908152602001604051809103902060009054906101000a900460ff16611b65576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611b5c9061392e565b60405180910390fd5b6000600182604051611b7791906138ba565b9081526020016040518091039020905060005b8180549050811015611bfd57600383604051611ba691906138ba565b9081526020016040518091039020828281548110611bc757611bc6613a70565b5b90600052602060002001604051611bde9190613f73565b9081526020016040518091039020600090558080600101915050611b8a565b50600182604051611c0e91906138ba565b90815260200160405180910390206000611c2891906127b4565b600282604051611c3891906138ba565b90815260200160405180910390206000611c5291906127d5565b81604051611c6091906138ba565b60405180910390207f372dd188f66e03080f62fc207ebf4954a98c81128ca2472aedfc273f0f7c788360405160405180910390a25050565b611ca0612793565b6000611cac848461263f565b90508015611efc57600284604051611cc491906138ba565b90815260200160405180910390206001600386604051611ce491906138ba565b908152602001604051809103902085604051611d0091906139f6565b908152602001604051809103902054611d199190613a3c565b81548110611d2a57611d29613a70565b5b9060005260206000209060030201604051806060016040529081600082018054611d5390613ace565b80601f0160208091040260200160405190810160405280929190818152602001828054611d7f90613ace565b8015611dcc5780601f10611da157610100808354040283529160200191611dcc565b820191906000526020600020905b815481529060010190602001808311611daf57829003601f168201915b50505050508152602001600182018054611de590613ace565b80601f0160208091040260200160405190810160405280929190818152602001828054611e1190613ace565b8015611e5e5780601f10611e3357610100808354040283529160200191611e5e565b820191906000526020600020905b815481529060010190602001808311611e4157829003601f168201915b50505050508152602001600282018054611e7790613ace565b80601f0160208091040260200160405190810160405280929190818152602001828054611ea390613ace565b8015611ef05780601f10611ec557610100808354040283529160200191611ef0565b820191906000526020600020905b815481529060010190602001808311611ed357829003601f168201915b50505050508152505091505b9250929050565b6000600480549050905090565b6000600182604051611f2291906138ba565b9081526020016040518091039020805490509050919050565b6000611f47838361263f565b905092915050565b611f576125b8565b60005b60048054905081101561214557600060048281548110611f7d57611f7c613a70565b5b906000526020600020018054611f9290613ace565b80601f0160208091040260200160405190810160405280929190818152602001828054611fbe90613ace565b801561200b5780601f10611fe05761010080835404028352916020019161200b565b820191906000526020600020905b815481529060010190602001808311611fee57829003601f168201915b50505050509050600060018260405161202491906138ba565b9081526020016040518091039020905060005b81805490508110156120aa5760038360405161205391906138ba565b908152602001604051809103902082828154811061207457612073613a70565b5b9060005260206000200160405161208b9190613f73565b9081526020016040518091039020600090558080600101915050612037565b506001826040516120bb91906138ba565b908152602001604051809103902060006120d591906127b4565b6002826040516120e591906138ba565b908152602001604051809103902060006120ff91906127d5565b600060058360405161211191906138ba565b908152602001604051809103902060006101000a81548160ff02191690831515021790555050508080600101915050611f5a565b506004600061215491906127f9565b7f30addec5e9e954699f286bae8e1558655b0d436c3d7b501014eb5c0b4a76e6db60405160405180910390a1565b61218a6125b8565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036121fc5760006040517f1e4fbdf70000000000000000000000000000000000000000000000000000000081526004016121f39190613690565b60405180910390fd5b61220581612687565b50565b6122106125b8565b6000835111612254576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161224b90614146565b60405180910390fd5b6000825111612298576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161228f906142ca565b60405180910390fd5b6005836040516122a891906138ba565b908152602001604051809103902060009054906101000a900460ff16612335576004839080600181540180825580915050600190039060005260206000200160009091909190915090816122fc91906141ac565b50600160058460405161230f91906138ba565b908152602001604051809103902060006101000a81548160ff0219169083151502179055505b61233f838361263f565b612490576001808460405161235491906138ba565b9081526020016040518091039020805490506123709190613ebc565b60038460405161238091906138ba565b90815260200160405180910390208360405161239c91906139f6565b9081526020016040518091039020819055506001836040516123be91906138ba565b9081526020016040518091039020829080600181540180825580915050600190039060005260206000200160009091909190915090816123fe91906142ea565b5060028360405161240f91906138ba565b9081526020016040518091039020819080600181540180825580915050600190039060005260206000209060030201600090919091909150600082015181600001908161245c91906142ea565b50602082015181600101908161247291906142ea565b50604082015181600201908161248891906142ea565b50505061255b565b806002846040516124a191906138ba565b908152602001604051809103902060016003866040516124c191906138ba565b9081526020016040518091039020856040516124dd91906139f6565b9081526020016040518091039020546124f69190613a3c565b8154811061250757612506613a70565b5b9060005260206000209060030201600082015181600001908161252a91906142ea565b50602082015181600101908161254091906142ea565b50604082015181600201908161255691906142ea565b509050505b8160405161256991906139f6565b60405180910390208360405161257f91906138ba565b60405180910390207fd00871f87cd1b1b4e50e5be511f060478c06a013856673c392f2adbfa65df8ad60405160405180910390a3505050565b6125c061274b565b73ffffffffffffffffffffffffffffffffffffffff166125de611606565b73ffffffffffffffffffffffffffffffffffffffff161461263d5761260161274b565b6040517f118cdaa70000000000000000000000000000000000000000000000000000000081526004016126349190613690565b60405180910390fd5b565b60008060038460405161265291906138ba565b90815260200160405180910390208360405161266e91906139f6565b9081526020016040518091039020541415905092915050565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050816000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b600033905090565b50805461275f90613ace565b6000825580601f106127715750612790565b601f01602090049060005260206000209081019061278f919061281a565b5b50565b60405180606001604052806060815260200160608152602001606081525090565b50805460008255906000526020600020908101906127d29190612837565b50565b50805460008255600302906000526020600020908101906127f6919061285b565b50565b508054600082559060005260206000209081019061281791906128a2565b50565b5b8082111561283357600081600090555060010161281b565b5090565b5b80821115612857576000818161284e9190612753565b50600101612838565b5090565b5b8082111561289e57600080820160006128759190612753565b6001820160006128859190612753565b6002820160006128959190612753565b5060030161285c565b5090565b5b808211156128c257600081816128b991906128c6565b506001016128a3565b5090565b5080546128d290613ace565b6000825580601f106128e45750612903565b601f016020900490600052602060002090810190612902919061281a565b5b50565b6000604051905090565b600080fd5b600080fd5b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b61296d82612924565b810181811067ffffffffffffffff8211171561298c5761298b612935565b5b80604052505050565b600061299f612906565b90506129ab8282612964565b919050565b600067ffffffffffffffff8211156129cb576129ca612935565b5b6129d482612924565b9050602081019050919050565b82818337600083830152505050565b6000612a036129fe846129b0565b612995565b905082815260208101848484011115612a1f57612a1e61291f565b5b612a2a8482856129e1565b509392505050565b600082601f830112612a4757612a4661291a565b5b8135612a578482602086016129f0565b91505092915050565b600067ffffffffffffffff821115612a7b57612a7a612935565b5b612a8482612924565b9050602081019050919050565b6000612aa4612a9f84612a60565b612995565b905082815260208101848484011115612ac057612abf61291f565b5b612acb8482856129e1565b509392505050565b600082601f830112612ae857612ae761291a565b5b8135612af8848260208601612a91565b91505092915050565b60008060408385031215612b1857612b17612910565b5b600083013567ffffffffffffffff811115612b3657612b35612915565b5b612b4285828601612a32565b925050602083013567ffffffffffffffff811115612b6357612b62612915565b5b612b6f85828601612ad3565b9150509250929050565b600067ffffffffffffffff821115612b9457612b93612935565b5b602082029050602081019050919050565b600080fd5b6000612bbd612bb884612b79565b612995565b90508083825260208201905060208402830185811115612be057612bdf612ba5565b5b835b81811015612c2757803567ffffffffffffffff811115612c0557612c0461291a565b5b808601612c128982612ad3565b85526020850194505050602081019050612be2565b5050509392505050565b600082601f830112612c4657612c4561291a565b5b8135612c56848260208601612baa565b91505092915050565b60008060408385031215612c7657612c75612910565b5b600083013567ffffffffffffffff811115612c9457612c93612915565b5b612ca085828601612a32565b925050602083013567ffffffffffffffff811115612cc157612cc0612915565b5b612ccd85828601612c31565b9150509250929050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b600081519050919050565b600082825260208201905092915050565b60005b83811015612d3d578082015181840152602081019050612d22565b60008484015250505050565b6000612d5482612d03565b612d5e8185612d0e565b9350612d6e818560208601612d1f565b612d7781612924565b840191505092915050565b60006060830160008301518482036000860152612d9f8282612d49565b91505060208301518482036020860152612db98282612d49565b91505060408301518482036040860152612dd38282612d49565b9150508091505092915050565b6000612dec8383612d82565b905092915050565b6000602082019050919050565b6000612e0c82612cd7565b612e168185612ce2565b935083602082028501612e2885612cf3565b8060005b85811015612e645784840389528151612e458582612de0565b9450612e5083612df4565b925060208a01995050600181019050612e2c565b50829750879550505050505092915050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b60008115159050919050565b612eb781612ea2565b82525050565b6000612ec98383612eae565b60208301905092915050565b6000602082019050919050565b6000612eed82612e76565b612ef78185612e81565b9350612f0283612e92565b8060005b83811015612f33578151612f1a8882612ebd565b9750612f2583612ed5565b925050600181019050612f06565b5085935050505092915050565b60006040820190508181036000830152612f5a8185612e01565b90508181036020830152612f6e8184612ee2565b90509392505050565b6000819050919050565b612f8a81612f77565b82525050565b6000602082019050612fa56000830184612f81565b92915050565b612fb481612f77565b8114612fbf57600080fd5b50565b600081359050612fd181612fab565b92915050565b600080600060608486031215612ff057612fef612910565b5b600084013567ffffffffffffffff81111561300e5761300d612915565b5b61301a86828701612a32565b935050602061302b86828701612fc2565b925050604061303c86828701612fc2565b9150509250925092565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b600061307e8383612d49565b905092915050565b6000602082019050919050565b600061309e82613046565b6130a88185613051565b9350836020820285016130ba85613062565b8060005b858110156130f657848403895281516130d78582613072565b94506130e283613086565b925060208a019950506001810190506130be565b50829750879550505050505092915050565b600060408201905081810360008301526131228185613093565b90506131316020830184612f81565b9392505050565b600067ffffffffffffffff82111561315357613152612935565b5b602082029050602081019050919050565b600080fd5b600080fd5b60006060828403121561318457613183613164565b5b61318e6060612995565b9050600082013567ffffffffffffffff8111156131ae576131ad613169565b5b6131ba84828501612ad3565b600083015250602082013567ffffffffffffffff8111156131de576131dd613169565b5b6131ea84828501612ad3565b602083015250604082013567ffffffffffffffff81111561320e5761320d613169565b5b61321a84828501612ad3565b60408301525092915050565b600061323961323484613138565b612995565b9050808382526020820190506020840283018581111561325c5761325b612ba5565b5b835b818110156132a357803567ffffffffffffffff8111156132815761328061291a565b5b80860161328e898261316e565b8552602085019450505060208101905061325e565b5050509392505050565b600082601f8301126132c2576132c161291a565b5b81356132d2848260208601613226565b91505092915050565b6000806000606084860312156132f4576132f3612910565b5b600084013567ffffffffffffffff81111561331257613311612915565b5b61331e86828701612a32565b935050602084013567ffffffffffffffff81111561333f5761333e612915565b5b61334b86828701612c31565b925050604084013567ffffffffffffffff81111561336c5761336b612915565b5b613378868287016132ad565b9150509250925092565b6000806040838503121561339957613398612910565b5b60006133a785828601612fc2565b92505060206133b885828601612fc2565b9150509250929050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b600081519050919050565b600082825260208201905092915050565b6000613415826133ee565b61341f81856133f9565b935061342f818560208601612d1f565b61343881612924565b840191505092915050565b600061344f838361340a565b905092915050565b6000602082019050919050565b600061346f826133c2565b61347981856133cd565b93508360208202850161348b856133de565b8060005b858110156134c757848403895281516134a88582613443565b94506134b383613457565b925060208a0199505060018101905061348f565b50829750879550505050505092915050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b61350e81612f77565b82525050565b60006135208383613505565b60208301905092915050565b6000602082019050919050565b6000613544826134d9565b61354e81856134e4565b9350613559836134f5565b8060005b8381101561358a5781516135718882613514565b975061357c8361352c565b92505060018101905061355d565b5085935050505092915050565b600060608201905081810360008301526135b18186613464565b905081810360208301526135c58185613539565b90506135d46040830184612f81565b949350505050565b6000602082840312156135f2576135f1612910565b5b600082013567ffffffffffffffff8111156136105761360f612915565b5b61361c84828501612a32565b91505092915050565b61362e81612ea2565b82525050565b60006020820190506136496000830184613625565b92915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061367a8261364f565b9050919050565b61368a8161366f565b82525050565b60006020820190506136a56000830184613681565b92915050565b600060608201905081810360008301526136c58186613093565b905081810360208301526136d98185612e01565b90506136e86040830184612f81565b949350505050565b6000606083016000830151848203600086015261370d8282612d49565b915050602083015184820360208601526137278282612d49565b915050604083015184820360408601526137418282612d49565b9150508091505092915050565b6000604082019050818103600083015261376881856136f0565b90506137776020830184613625565b9392505050565b6137878161366f565b811461379257600080fd5b50565b6000813590506137a48161377e565b92915050565b6000602082840312156137c0576137bf612910565b5b60006137ce84828501613795565b91505092915050565b6000806000606084860312156137f0576137ef612910565b5b600084013567ffffffffffffffff81111561380e5761380d612915565b5b61381a86828701612a32565b935050602084013567ffffffffffffffff81111561383b5761383a612915565b5b61384786828701612ad3565b925050604084013567ffffffffffffffff81111561386857613867612915565b5b6138748682870161316e565b9150509250925092565b600081905092915050565b6000613894826133ee565b61389e818561387e565b93506138ae818560208601612d1f565b80840191505092915050565b60006138c68284613889565b915081905092915050565b600082825260208201905092915050565b7f4e616d65737061636520646f6573206e6f742065786973740000000000000000600082015250565b60006139186018836138d1565b9150613923826138e2565b602082019050919050565b600060208201905081810360008301526139478161390b565b9050919050565b7f4b657920646f6573206e6f7420657869737420696e206e616d65737061636500600082015250565b6000613984601f836138d1565b915061398f8261394e565b602082019050919050565b600060208201905081810360008301526139b381613977565b9050919050565b600081905092915050565b60006139d082612d03565b6139da81856139ba565b93506139ea818560208601612d1f565b80840191505092915050565b6000613a0282846139c5565b915081905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000613a4782612f77565b9150613a5283612f77565b9250828203905081811115613a6a57613a69613a0d565b5b92915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b60006002820490506001821680613ae657607f821691505b602082108103613af957613af8613a9f565b5b50919050565b600081549050613b0e81613ace565b9050919050565b60008190508160005260206000209050919050565b60008190508160005260206000209050919050565b60006020601f8301049050919050565b600082821b905092915050565b600060088302613b8c7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82613b4f565b613b968683613b4f565b95508019841693508086168417925050509392505050565b6000819050919050565b6000613bd3613bce613bc984612f77565b613bae565b612f77565b9050919050565b6000819050919050565b613bed83613bb8565b613c01613bf982613bda565b848454613b5c565b825550505050565b600090565b613c16613c09565b613c21818484613be4565b505050565b5b81811015613c4557613c3a600082613c0e565b600181019050613c27565b5050565b601f821115613c8a57613c5b81613b15565b613c6484613b3f565b81016020851015613c73578190505b613c87613c7f85613b3f565b830182613c26565b50505b505050565b600082821c905092915050565b6000613cad60001984600802613c8f565b1980831691505092915050565b6000613cc68383613c9c565b9150826002028217905092915050565b818103613ce4575050613dbc565b613ced82613aff565b67ffffffffffffffff811115613d0657613d05612935565b5b613d108254613ace565b613d1b828285613c49565b6000601f831160018114613d4a5760008415613d38578287015490505b613d428582613cba565b865550613db5565b601f198416613d5887613b2a565b9650613d6386613b15565b60005b82811015613d8b57848901548255600182019150600185019450602081019050613d66565b86831015613da85784890154613da4601f891682613c9c565b8355505b6001600288020188555050505b5050505050505b565b600081549050613dcd81613ace565b9050919050565b818103613de2575050613eba565b613deb82613dbe565b67ffffffffffffffff811115613e0457613e03612935565b5b613e0e8254613ace565b613e19828285613c49565b6000601f831160018114613e485760008415613e36578287015490505b613e408582613cba565b865550613eb3565b601f198416613e5687613b15565b9650613e6186613b15565b60005b82811015613e8957848901548255600182019150600185019450602081019050613e64565b86831015613ea65784890154613ea2601f891682613c9c565b8355505b6001600288020188555050505b5050505050505b565b6000613ec782612f77565b9150613ed283612f77565b9250828201905080821115613eea57613ee9613a0d565b5b92915050565b60008154613efd81613ace565b613f0781866139ba565b94506001821660008114613f225760018114613f3757613f6a565b60ff1983168652811515820286019350613f6a565b613f4085613b15565b60005b83811015613f6257815481890152600182019150602081019050613f43565b838801955050505b50505092915050565b6000613f7f8284613ef0565b915081905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b60008190508160005260206000209050919050565b60008154613fdb81613ace565b613fe5818661387e565b94506001821660008114614000576001811461401557614048565b60ff1983168652811515820286019350614048565b61401e85613fb9565b60005b8381101561404057815481890152600182019150602081019050614021565b838801955050505b50505092915050565b600061405d8284613fce565b915081905092915050565b7f4b65797320616e642076616c75657320617272617973206d757374206861766560008201527f2073616d65206c656e6774680000000000000000000000000000000000000000602082015250565b60006140c4602c836138d1565b91506140cf82614068565b604082019050919050565b600060208201905081810360008301526140f3816140b7565b9050919050565b7f4e616d6573706163652063616e6e6f7420626520656d70747900000000000000600082015250565b60006141306019836138d1565b915061413b826140fa565b602082019050919050565b6000602082019050818103600083015261415f81614123565b9050919050565b601f8211156141a75761417881613fb9565b61418184613b3f565b81016020851015614190578190505b6141a461419c85613b3f565b830182613c26565b50505b505050565b6141b5826133ee565b67ffffffffffffffff8111156141ce576141cd612935565b5b6141d88254613ace565b6141e3828285614166565b600060209050601f8311600181146142165760008415614204578287015190505b61420e8582613cba565b865550614276565b601f19841661422486613fb9565b60005b8281101561424c57848901518255600182019150602085019450602081019050614227565b868310156142695784890151614265601f891682613c9c565b8355505b6001600288020188555050505b505050505050565b7f4b65792063616e6e6f7420626520656d70747900000000000000000000000000600082015250565b60006142b46013836138d1565b91506142bf8261427e565b602082019050919050565b600060208201905081810360008301526142e3816142a7565b9050919050565b6142f382612d03565b67ffffffffffffffff81111561430c5761430b612935565b5b6143168254613ace565b614321828285613c49565b600060209050601f8311600181146143545760008415614342578287015190505b61434c8582613cba565b8655506143b4565b601f19841661436286613b15565b60005b8281101561438a57848901518255600182019150602085019450602081019050614365565b868310156143a757848901516143a3601f891682613c9c565b8355505b6001600288020188555050505b50505050505056fea264697066735822122096c0c5fe64f7732f41c7ca9f43cb55beaffdda0ec283aa67937fd742c931d6e464736f6c63430008180033" From 2efec6498a0b68ed50e5644561d44094eaacdb69 Mon Sep 17 00:00:00 2001 From: envestcc Date: Thu, 11 Sep 2025 20:46:14 +0800 Subject: [PATCH 15/26] store account additional fields in contract --- .../execution/evm/evmstatedbadapter_erigon.go | 1 - api/coreservice.go | 5 ++ state/account.go | 3 +- state/factory/erigonstore/contract_backend.go | 61 ++++++++++++++++--- .../workingsetstore_erigon_simulate.go | 12 +--- state/state.go | 2 +- systemcontracts/systemcontracts.go | 2 + 7 files changed, 63 insertions(+), 23 deletions(-) diff --git a/action/protocol/execution/evm/evmstatedbadapter_erigon.go b/action/protocol/execution/evm/evmstatedbadapter_erigon.go index 2a5b48e994..d19140107d 100644 --- a/action/protocol/execution/evm/evmstatedbadapter_erigon.go +++ b/action/protocol/execution/evm/evmstatedbadapter_erigon.go @@ -119,7 +119,6 @@ func (s *ErigonStateDBAdapter) CreateAccount(evmAddr common.Address) { // SetNonce sets the nonce of the given address func (s *ErigonStateDBAdapter) SetNonce(evmAddr common.Address, n uint64) { - s.StateDBAdapter.SetNonce(evmAddr, n) // nonce updates for erigon will be done in statedb } diff --git a/api/coreservice.go b/api/coreservice.go index 3f1a45be26..d0340480f7 100644 --- a/api/coreservice.go +++ b/api/coreservice.go @@ -2243,6 +2243,11 @@ func (core *coreService) workingSetAt(ctx context.Context, height uint64) (conte if err != nil { return ctx, nil, status.Error(codes.Internal, err.Error()) } + bcCtx := protocol.MustGetBlockchainCtx(ctx) + ctx = protocol.WithBlockCtx(ctx, protocol.BlockCtx{ + BlockHeight: bcCtx.Tip.Height, + BlockTimeStamp: bcCtx.Tip.Timestamp, + }) ws, err := core.sf.WorkingSetAtHeight(ctx, height) if err != nil { return ctx, nil, status.Error(codes.Internal, err.Error()) diff --git a/state/account.go b/state/account.go index ef9a7baaa1..d0f4f07e9f 100644 --- a/state/account.go +++ b/state/account.go @@ -277,8 +277,7 @@ func (st *Account) StoreToContract(ns string, key []byte, backend ContractBacken if err != nil { return errors.Wrapf(err, "failed to convert key to address %x", key) } - backend.PutAccount(addr, st) - return nil + return backend.PutAccount(addr, st) } func (st *Account) LoadFromContract(ns string, key []byte, backend ContractBackend) error { diff --git a/state/factory/erigonstore/contract_backend.go b/state/factory/erigonstore/contract_backend.go index 27c82eb48b..c09838f88b 100644 --- a/state/factory/erigonstore/contract_backend.go +++ b/state/factory/erigonstore/contract_backend.go @@ -10,22 +10,27 @@ import ( "github.com/erigontech/erigon-lib/chain" erigonComm "github.com/erigontech/erigon-lib/common" erigonstate "github.com/erigontech/erigon/core/state" + "github.com/erigontech/erigon/core/types/accounts" erigonAcc "github.com/erigontech/erigon/core/types/accounts" "github.com/erigontech/erigon/core/vm" "github.com/erigontech/erigon/core/vm/evmtypes" "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/common" "github.com/holiman/uint256" "github.com/pkg/errors" "go.uber.org/zap" + "google.golang.org/protobuf/proto" "github.com/iotexproject/iotex-address/address" "github.com/iotexproject/iotex-core/v2/action/protocol" + "github.com/iotexproject/iotex-core/v2/action/protocol/account/accountpb" "github.com/iotexproject/iotex-core/v2/action/protocol/execution/evm" iotexevm "github.com/iotexproject/iotex-core/v2/action/protocol/execution/evm" "github.com/iotexproject/iotex-core/v2/blockchain/genesis" "github.com/iotexproject/iotex-core/v2/pkg/log" "github.com/iotexproject/iotex-core/v2/state" + "github.com/iotexproject/iotex-core/v2/systemcontracts" ) type ( @@ -95,7 +100,7 @@ func (backend *contractBacked) Exists(addr address.Address) bool { return backend.intraBlockState.Exist(erigonComm.BytesToAddress(addr.Bytes())) } -func (backend *contractBacked) PutAccount(_addr address.Address, acc *state.Account) { +func (backend *contractBacked) PutAccount(_addr address.Address, acc *state.Account) error { addr := erigonComm.BytesToAddress(_addr.Bytes()) if !backend.intraBlockState.Exist(addr) { backend.intraBlockState.CreateAccount(addr, acc.IsContract()) @@ -108,6 +113,19 @@ func (backend *contractBacked) PutAccount(_addr address.Address, acc *state.Acco nonce = acc.PendingNonceConsideringFreshAccount() } backend.intraBlockState.SetNonce(addr, nonce) + // store other fields in the account storage contract + pbAcc := acc.ToProto() + pbAcc.Balance = "" + pbAcc.Nonce = 0 + data, err := proto.Marshal(pbAcc) + if err != nil { + return errors.Wrapf(err, "failed to marshal account %x", addr.Bytes()) + } + contract, err := systemcontracts.NewGenericStorageContract(backend.accountContractAddr(), backend) + if err != nil { + return errors.Wrapf(err, "failed to create account storage contract for address %x", addr.Bytes()) + } + return contract.Put(_addr.Bytes(), systemcontracts.GenericValue{PrimaryData: data}) } func (backend *contractBacked) Account(_addr address.Address) (*state.Account, error) { @@ -115,20 +133,47 @@ func (backend *contractBacked) Account(_addr address.Address) (*state.Account, e if !backend.intraBlockState.Exist(addr) { return nil, errors.Wrapf(state.ErrStateNotExist, "address: %x", addr.Bytes()) } + // load other fields from the account storage contract + contract, err := systemcontracts.NewGenericStorageContract(backend.accountContractAddr(), backend) + if err != nil { + return nil, errors.Wrapf(err, "failed to create account storage contract for address %x", addr.Bytes()) + } + value, err := contract.Get(_addr.Bytes()) + if err != nil { + return nil, errors.Wrapf(err, "failed to get account data for address %x", addr.Bytes()) + } + if !value.KeyExists { + return nil, errors.Errorf("account info not found for address %x", addr.Bytes()) + } + pbAcc := &accountpb.Account{} + if err := proto.Unmarshal(value.Value.PrimaryData, pbAcc); err != nil { + return nil, errors.Wrapf(err, "failed to unmarshal account data for address %x", addr.Bytes()) + } + balance := backend.intraBlockState.GetBalance(addr) nonce := backend.intraBlockState.GetNonce(addr) - acc, err := state.NewAccount() - if err != nil { - return nil, errors.Wrap(err, "failed to create account") + pbAcc.Balance = balance.String() + switch pbAcc.Type { + case accountpb.AccountType_ZERO_NONCE: + pbAcc.Nonce = nonce + case accountpb.AccountType_DEFAULT: + pbAcc.Nonce = nonce - 1 + default: + return nil, errors.Errorf("unknown account type %v for address %x", pbAcc.Type, addr.Bytes()) } - acc.AddBalance(balance.ToBig()) - acc.SetPendingNonce(nonce) - if ch := backend.intraBlockState.GetCodeHash(addr); len(ch) > 0 { - acc.CodeHash = ch.Bytes() + + if ch := backend.intraBlockState.GetCodeHash(addr); !accounts.IsEmptyCodeHash(ch) { + pbAcc.CodeHash = ch.Bytes() } + acc := &state.Account{} + acc.FromProto(pbAcc) return acc, nil } +func (backend *contractBacked) accountContractAddr() common.Address { + return common.BytesToAddress(systemcontracts.SystemContracts[systemcontracts.AccountInfoContractIndex].Address.Bytes()) +} + func (backend *contractBacked) prepare(intra evmtypes.IntraBlockState) (*vm.EVM, error) { // deploy system contracts diff --git a/state/factory/workingsetstore_erigon_simulate.go b/state/factory/workingsetstore_erigon_simulate.go index 2c99f667ec..ff9c27c8d3 100644 --- a/state/factory/workingsetstore_erigon_simulate.go +++ b/state/factory/workingsetstore_erigon_simulate.go @@ -5,9 +5,7 @@ import ( "github.com/iotexproject/go-pkgs/hash" - "github.com/iotexproject/iotex-core/v2/action/protocol/execution/evm" "github.com/iotexproject/iotex-core/v2/db" - "github.com/iotexproject/iotex-core/v2/state" "github.com/iotexproject/iotex-core/v2/state/factory/erigonstore" ) @@ -41,15 +39,7 @@ func (store *erigonWorkingSetStoreForSimulate) GetObject(ns string, key []byte, if storage != nil { return store.erigonStore.GetObject(ns, key, obj) } - if _, ok := obj.(*state.Account); !ok && ns == AccountKVNamespace { - return store.store.GetObject(ns, key, obj) - } - switch ns { - case AccountKVNamespace, evm.CodeKVNameSpace: - return store.erigonStore.GetObject(ns, key, obj) - default: - return store.store.GetObject(ns, key, obj) - } + return store.store.GetObject(ns, key, obj) } func (store *erigonWorkingSetStoreForSimulate) States(ns string, keys [][]byte, obj any) ([][]byte, [][]byte, error) { diff --git a/state/state.go b/state/state.go index 4be58ce099..6dce1021f8 100644 --- a/state/state.go +++ b/state/state.go @@ -57,6 +57,6 @@ func Deserialize(x interface{}, data []byte) error { type ContractBackend interface { systemcontracts.ContractBackend - PutAccount(addr address.Address, acc *Account) + PutAccount(addr address.Address, acc *Account) error Account(addr address.Address) (*Account, error) } diff --git a/systemcontracts/systemcontracts.go b/systemcontracts/systemcontracts.go index df83219409..2e8e1a1a8d 100644 --- a/systemcontracts/systemcontracts.go +++ b/systemcontracts/systemcontracts.go @@ -50,6 +50,8 @@ const ( RewardingContractV2Index // StakingViewContractIndex is the system contract for staking view storage StakingViewContractIndex + // AccountInfoContractIndex is the system contract for account info storage + AccountInfoContractIndex // SystemContractCount is the total number of system contracts SystemContractCount ) From 7ac143c766278a22c23dd272cdcba4eb1c722807 Mon Sep 17 00:00:00 2001 From: envestcc Date: Fri, 12 Sep 2025 14:32:45 +0800 Subject: [PATCH 16/26] fix test --- .../execution/evm/evmstatedbadapter_erigon.go | 1 + api/coreservice.go | 13 ++++++++++--- api/coreservice_test.go | 3 +++ 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/action/protocol/execution/evm/evmstatedbadapter_erigon.go b/action/protocol/execution/evm/evmstatedbadapter_erigon.go index d19140107d..2a5b48e994 100644 --- a/action/protocol/execution/evm/evmstatedbadapter_erigon.go +++ b/action/protocol/execution/evm/evmstatedbadapter_erigon.go @@ -119,6 +119,7 @@ func (s *ErigonStateDBAdapter) CreateAccount(evmAddr common.Address) { // SetNonce sets the nonce of the given address func (s *ErigonStateDBAdapter) SetNonce(evmAddr common.Address, n uint64) { + s.StateDBAdapter.SetNonce(evmAddr, n) // nonce updates for erigon will be done in statedb } diff --git a/api/coreservice.go b/api/coreservice.go index d0340480f7..e4a1f0fe02 100644 --- a/api/coreservice.go +++ b/api/coreservice.go @@ -2200,12 +2200,22 @@ func (core *coreService) simulateExecution( if err != nil { return nil, nil, status.Error(codes.Internal, err.Error()) } + bcCtx := protocol.MustGetBlockchainCtx(ctx) + ctx = protocol.WithFeatureCtx(protocol.WithBlockCtx(ctx, protocol.BlockCtx{ + BlockHeight: bcCtx.Tip.Height, + BlockTimeStamp: bcCtx.Tip.Timestamp, + })) ws, err = core.sf.WorkingSetAtHeight(ctx, height) } else { ctx, err = core.bc.Context(ctx) if err != nil { return nil, nil, status.Error(codes.Internal, err.Error()) } + bcCtx := protocol.MustGetBlockchainCtx(ctx) + ctx = protocol.WithFeatureCtx(protocol.WithBlockCtx(ctx, protocol.BlockCtx{ + BlockHeight: bcCtx.Tip.Height, + BlockTimeStamp: bcCtx.Tip.Timestamp, + })) ws, err = core.sf.WorkingSet(ctx) } if err != nil { @@ -2217,9 +2227,6 @@ func (core *coreService) simulateExecution( return nil, nil, status.Error(codes.InvalidArgument, err.Error()) } var pendingNonce uint64 - ctx = protocol.WithFeatureCtx(protocol.WithBlockCtx(ctx, protocol.BlockCtx{ - BlockHeight: height, - })) bcCtx := protocol.MustGetBlockchainCtx(ctx) if protocol.MustGetFeatureCtx(ctx).UseZeroNonceForFreshAccount { pendingNonce = state.PendingNonceConsideringFreshAccount() diff --git a/api/coreservice_test.go b/api/coreservice_test.go index afbef43af1..26994f3fb5 100644 --- a/api/coreservice_test.go +++ b/api/coreservice_test.go @@ -492,6 +492,9 @@ func TestEstimateExecutionGasConsumption(t *testing.T) { bc.EXPECT().Genesis().Return(genesis.Genesis{}).Times(1) bc.EXPECT().TipHeight().Return(uint64(1)).Times(2) + ctx := protocol.WithBlockchainCtx(genesis.WithGenesisContext(ctx, genesis.Genesis{}), protocol.BlockchainCtx{ + Tip: protocol.TipInfo{Height: 1, Timestamp: time.Now()}, + }) bc.EXPECT().ContextAtHeight(gomock.Any(), gomock.Any()).Return(ctx, nil).Times(1) sf.EXPECT().WorkingSetAtHeight(gomock.Any(), gomock.Any()).Return(&mockWS{}, nil).Times(1) elp := (&action.EnvelopeBuilder{}).SetAction(&action.Execution{}).Build() From 96538380c5d0538cca55ef651ffa9615c41fa7e7 Mon Sep 17 00:00:00 2001 From: envestcc Date: Mon, 15 Sep 2025 08:53:58 +0800 Subject: [PATCH 17/26] address comment --- state/factory/erigonstore/contract_backend.go | 35 ++++++++-------- state/factory/erigonstore/contract_storage.go | 2 +- .../contract_storage_namespaced.go | 14 +++---- .../erigonstore/contract_storage_standard.go | 15 +++---- .../erigonstore/workingsetstore_erigon.go | 41 +++++++++++++++++-- 5 files changed, 71 insertions(+), 36 deletions(-) diff --git a/state/factory/erigonstore/contract_backend.go b/state/factory/erigonstore/contract_backend.go index c09838f88b..9be1a98a71 100644 --- a/state/factory/erigonstore/contract_backend.go +++ b/state/factory/erigonstore/contract_backend.go @@ -34,39 +34,42 @@ import ( ) type ( - contractBacked struct { + contractBackend struct { intraBlockState *erigonstate.IntraBlockState org erigonstate.StateReader // helper fields height uint64 timestamp time.Time + producer erigonComm.Address g *genesis.Genesis evmNetworkID uint32 } ) -func NewContractBackend(intraBlockState *erigonstate.IntraBlockState, org erigonstate.StateReader, height uint64, timestamp time.Time, g *genesis.Genesis, evmNetworkID uint32) *contractBacked { - return &contractBacked{ +// NewContractBackend creates a new contract backend for system contract interaction +func NewContractBackend(intraBlockState *erigonstate.IntraBlockState, org erigonstate.StateReader, height uint64, timestamp time.Time, producer address.Address, g *genesis.Genesis, evmNetworkID uint32) *contractBackend { + return &contractBackend{ intraBlockState: intraBlockState, org: org, height: height, timestamp: timestamp, g: g, evmNetworkID: evmNetworkID, + producer: erigonComm.BytesToAddress(producer.Bytes()), } } -func (backend *contractBacked) Call(callMsg *ethereum.CallMsg) ([]byte, error) { +func (backend *contractBackend) Call(callMsg *ethereum.CallMsg) ([]byte, error) { return backend.call(callMsg, erigonstate.New(&intraStateReader{backend.intraBlockState, backend.org})) } -func (backend *contractBacked) Handle(callMsg *ethereum.CallMsg) error { +func (backend *contractBackend) Handle(callMsg *ethereum.CallMsg) error { _, err := backend.call(callMsg, backend.intraBlockState) return err } -func (backend *contractBacked) Deploy(callMsg *ethereum.CallMsg) (address.Address, error) { +func (backend *contractBackend) Deploy(callMsg *ethereum.CallMsg) (address.Address, error) { evm, err := backend.prepare(backend.intraBlockState) if err != nil { return nil, errors.Wrap(err, "failed to prepare EVM for contract deployment") @@ -85,7 +88,7 @@ func (backend *contractBacked) Deploy(callMsg *ethereum.CallMsg) (address.Addres } return nil, errors.Wrap(err, "failed to deploy contract") } - log.L().Info("EVM deployment result", + log.L().Debug("EVM deployment result", zap.String("from", callMsg.From.String()), zap.String("data", hex.EncodeToString(callMsg.Data)), zap.String("ret", hex.EncodeToString(ret)), @@ -96,11 +99,11 @@ func (backend *contractBacked) Deploy(callMsg *ethereum.CallMsg) (address.Addres return address.FromBytes(addr.Bytes()) } -func (backend *contractBacked) Exists(addr address.Address) bool { +func (backend *contractBackend) Exists(addr address.Address) bool { return backend.intraBlockState.Exist(erigonComm.BytesToAddress(addr.Bytes())) } -func (backend *contractBacked) PutAccount(_addr address.Address, acc *state.Account) error { +func (backend *contractBackend) PutAccount(_addr address.Address, acc *state.Account) error { addr := erigonComm.BytesToAddress(_addr.Bytes()) if !backend.intraBlockState.Exist(addr) { backend.intraBlockState.CreateAccount(addr, acc.IsContract()) @@ -128,7 +131,7 @@ func (backend *contractBacked) PutAccount(_addr address.Address, acc *state.Acco return contract.Put(_addr.Bytes(), systemcontracts.GenericValue{PrimaryData: data}) } -func (backend *contractBacked) Account(_addr address.Address) (*state.Account, error) { +func (backend *contractBackend) Account(_addr address.Address) (*state.Account, error) { addr := erigonComm.BytesToAddress(_addr.Bytes()) if !backend.intraBlockState.Exist(addr) { return nil, errors.Wrapf(state.ErrStateNotExist, "address: %x", addr.Bytes()) @@ -170,13 +173,11 @@ func (backend *contractBacked) Account(_addr address.Address) (*state.Account, e return acc, nil } -func (backend *contractBacked) accountContractAddr() common.Address { +func (backend *contractBackend) accountContractAddr() common.Address { return common.BytesToAddress(systemcontracts.SystemContracts[systemcontracts.AccountInfoContractIndex].Address.Bytes()) } -func (backend *contractBacked) prepare(intra evmtypes.IntraBlockState) (*vm.EVM, error) { - - // deploy system contracts +func (backend *contractBackend) prepare(intra evmtypes.IntraBlockState) (*vm.EVM, error) { blkCtxE := evmtypes.BlockContext{ CanTransfer: func(state evmtypes.IntraBlockState, addr erigonComm.Address, amount *uint256.Int) bool { log.L().Debug("CanTransfer called in erigon genesis state creation", @@ -206,7 +207,7 @@ func (backend *contractBacked) prepare(intra evmtypes.IntraBlockState) (*vm.EVM, ) return }, - Coinbase: erigonComm.Address{}, + Coinbase: backend.producer, GasLimit: math.MaxUint64, MaxGasLimit: true, BlockNumber: backend.height, @@ -273,7 +274,7 @@ func (backend *contractBacked) prepare(intra evmtypes.IntraBlockState) (*vm.EVM, return evm, nil } -func (backend *contractBacked) call(callMsg *ethereum.CallMsg, intra evmtypes.IntraBlockState) ([]byte, error) { +func (backend *contractBackend) call(callMsg *ethereum.CallMsg, intra evmtypes.IntraBlockState) ([]byte, error) { evm, err := backend.prepare(intra) if err != nil { return nil, errors.Wrap(err, "failed to prepare EVM for contract call") @@ -295,7 +296,7 @@ func (backend *contractBacked) call(callMsg *ethereum.CallMsg, intra evmtypes.In } return ret, errors.Wrapf(err, "error when system contract %x action mutates states", callMsg.To.Bytes()) } - log.L().Info("EVM call result", + log.L().Debug("EVM call result", zap.String("from", callMsg.From.String()), zap.String("to", callMsg.To.String()), zap.Uint64("dataSize", uint64(len(callMsg.Data))), diff --git a/state/factory/erigonstore/contract_storage.go b/state/factory/erigonstore/contract_storage.go index 3d187bad6b..ae8c57d25a 100644 --- a/state/factory/erigonstore/contract_storage.go +++ b/state/factory/erigonstore/contract_storage.go @@ -19,7 +19,7 @@ type ContractStorage interface { // ContractStorageStandard defines the interface for standard contract storage operations type ContractStorageStandard interface { - ContractStorageAddress(ns string, key []byte) (address.Address, error) + ContractStorageAddress(ns string) (address.Address, error) New() ContractStorageStandard Serialize() ([]byte, error) Deserialize([]byte) error diff --git a/state/factory/erigonstore/contract_storage_namespaced.go b/state/factory/erigonstore/contract_storage_namespaced.go index 59293c5b0f..32b1759b92 100644 --- a/state/factory/erigonstore/contract_storage_namespaced.go +++ b/state/factory/erigonstore/contract_storage_namespaced.go @@ -21,7 +21,7 @@ func NewContractStorageNamespacedWrapper(standard ContractStorageStandard) Contr } func (cs *contractStorageNamespacedWrapper) StoreToContract(ns string, key []byte, backend ContractBackend) error { - contract, err := cs.storageContract(ns, key, backend) + contract, err := cs.storageContract(ns, backend) if err != nil { return err } @@ -37,7 +37,7 @@ func (cs *contractStorageNamespacedWrapper) StoreToContract(ns string, key []byt } func (cs *contractStorageNamespacedWrapper) LoadFromContract(ns string, key []byte, backend ContractBackend) error { - contract, err := cs.storageContract(ns, key, backend) + contract, err := cs.storageContract(ns, backend) if err != nil { return err } @@ -56,7 +56,7 @@ func (cs *contractStorageNamespacedWrapper) LoadFromContract(ns string, key []by } func (cs *contractStorageNamespacedWrapper) DeleteFromContract(ns string, key []byte, backend ContractBackend) error { - contract, err := cs.storageContract(ns, key, backend) + contract, err := cs.storageContract(ns, backend) if err != nil { return err } @@ -68,7 +68,7 @@ func (cs *contractStorageNamespacedWrapper) DeleteFromContract(ns string, key [] } func (cs *contractStorageNamespacedWrapper) ListFromContract(ns string, backend ContractBackend) ([][]byte, []any, error) { - contract, err := cs.storageContract(ns, nil, backend) + contract, err := cs.storageContract(ns, backend) if err != nil { return nil, nil, err } @@ -97,7 +97,7 @@ func (cs *contractStorageNamespacedWrapper) ListFromContract(ns string, backend } func (cs *contractStorageNamespacedWrapper) BatchFromContract(ns string, keys [][]byte, backend ContractBackend) ([]any, error) { - contract, err := cs.storageContract(ns, nil, backend) + contract, err := cs.storageContract(ns, backend) if err != nil { return nil, err } @@ -121,8 +121,8 @@ func (cs *contractStorageNamespacedWrapper) BatchFromContract(ns string, keys [] return results, nil } -func (cs *contractStorageNamespacedWrapper) storageContract(ns string, key []byte, backend ContractBackend) (*systemcontracts.NamespaceStorageContract, error) { - addr, err := cs.standard.ContractStorageAddress(ns, key) +func (cs *contractStorageNamespacedWrapper) storageContract(ns string, backend ContractBackend) (*systemcontracts.NamespaceStorageContract, error) { + addr, err := cs.standard.ContractStorageAddress(ns) if err != nil { return nil, err } diff --git a/state/factory/erigonstore/contract_storage_standard.go b/state/factory/erigonstore/contract_storage_standard.go index ddd8a3c7e2..2cbec56565 100644 --- a/state/factory/erigonstore/contract_storage_standard.go +++ b/state/factory/erigonstore/contract_storage_standard.go @@ -13,12 +13,13 @@ type contractStorageStandardWrapper struct { standard ContractStorageStandard } +// NewContractStorageStandardWrapper creates a new ContractStorage wrapper for standard storage func NewContractStorageStandardWrapper(standard ContractStorageStandard) ContractStorage { return &contractStorageStandardWrapper{standard: standard} } func (cs *contractStorageStandardWrapper) StoreToContract(ns string, key []byte, backend ContractBackend) error { - contract, err := cs.storageContract(ns, key, backend) + contract, err := cs.storageContract(ns, backend) if err != nil { return err } @@ -33,7 +34,7 @@ func (cs *contractStorageStandardWrapper) StoreToContract(ns string, key []byte, } func (cs *contractStorageStandardWrapper) LoadFromContract(ns string, key []byte, backend ContractBackend) error { - contract, err := cs.storageContract(ns, key, backend) + contract, err := cs.storageContract(ns, backend) if err != nil { return err } @@ -51,7 +52,7 @@ func (cs *contractStorageStandardWrapper) LoadFromContract(ns string, key []byte } func (cs *contractStorageStandardWrapper) DeleteFromContract(ns string, key []byte, backend ContractBackend) error { - contract, err := cs.storageContract(ns, key, backend) + contract, err := cs.storageContract(ns, backend) if err != nil { return err } @@ -62,7 +63,7 @@ func (cs *contractStorageStandardWrapper) DeleteFromContract(ns string, key []by } func (cs *contractStorageStandardWrapper) ListFromContract(ns string, backend ContractBackend) ([][]byte, []any, error) { - contract, err := cs.storageContract(ns, nil, backend) + contract, err := cs.storageContract(ns, backend) if err != nil { return nil, nil, err } @@ -91,7 +92,7 @@ func (cs *contractStorageStandardWrapper) ListFromContract(ns string, backend Co } func (cs *contractStorageStandardWrapper) BatchFromContract(ns string, keys [][]byte, backend ContractBackend) ([]any, error) { - contract, err := cs.storageContract(ns, nil, backend) + contract, err := cs.storageContract(ns, backend) if err != nil { return nil, err } @@ -115,8 +116,8 @@ func (cs *contractStorageStandardWrapper) BatchFromContract(ns string, keys [][] return results, nil } -func (cs *contractStorageStandardWrapper) storageContract(ns string, key []byte, backend ContractBackend) (*systemcontracts.GenericStorageContract, error) { - addr, err := cs.standard.ContractStorageAddress(ns, key) +func (cs *contractStorageStandardWrapper) storageContract(ns string, backend ContractBackend) (*systemcontracts.GenericStorageContract, error) { + addr, err := cs.standard.ContractStorageAddress(ns) if err != nil { return nil, err } diff --git a/state/factory/erigonstore/workingsetstore_erigon.go b/state/factory/erigonstore/workingsetstore_erigon.go index 7e5c0401f5..18f77a9e4e 100644 --- a/state/factory/erigonstore/workingsetstore_erigon.go +++ b/state/factory/erigonstore/workingsetstore_erigon.go @@ -38,11 +38,13 @@ var ( heightKey = []byte("height") ) +// ErigonDB implements the Erigon database type ErigonDB struct { path string rw kv.RwDB } +// ErigonWorkingSetStore implements the Erigon working set store type ErigonWorkingSetStore struct { db *ErigonDB intraBlockState *erigonstate.IntraBlockState @@ -51,10 +53,12 @@ type ErigonWorkingSetStore struct { ctx context.Context } +// NewErigonDB creates a new ErigonDB func NewErigonDB(path string) *ErigonDB { return &ErigonDB{path: path} } +// Start starts the ErigonDB func (db *ErigonDB) Start(ctx context.Context) error { log.L().Info("starting history state index") lg := erigonlog.New() @@ -70,12 +74,14 @@ func (db *ErigonDB) Start(ctx context.Context) error { return nil } +// Stop stops the ErigonDB func (db *ErigonDB) Stop(ctx context.Context) { if db.rw != nil { db.rw.Close() } } +// NewErigonStore creates a new ErigonWorkingSetStore func (db *ErigonDB) NewErigonStore(ctx context.Context, height uint64) (*ErigonWorkingSetStore, error) { tx, err := db.rw.BeginRo(ctx) if err != nil { @@ -92,6 +98,7 @@ func (db *ErigonDB) NewErigonStore(ctx context.Context, height uint64) (*ErigonW }, nil } +// NewErigonStoreDryrun creates a new ErigonWorkingSetStore for dryrun func (db *ErigonDB) NewErigonStoreDryrun(ctx context.Context, height uint64) (*ErigonWorkingSetStore, error) { tx, err := db.rw.BeginRo(ctx) if err != nil { @@ -108,6 +115,7 @@ func (db *ErigonDB) NewErigonStoreDryrun(ctx context.Context, height uint64) (*E }, nil } +// BatchPrune prunes the ErigonWorkingSetStore in batches func (db *ErigonDB) BatchPrune(ctx context.Context, from, to, batch uint64) error { if from >= to { return errors.Errorf("invalid prune range: from %d >= to %d", from, to) @@ -144,6 +152,7 @@ func (db *ErigonDB) BatchPrune(ctx context.Context, from, to, batch uint64) erro return db.Prune(ctx, nil, from, to) } +// Prune prunes the ErigonWorkingSetStore from 'from' to 'to' func (db *ErigonDB) Prune(ctx context.Context, tx kv.RwTx, from, to uint64) error { if from >= to { return errors.Errorf("invalid prune range: from %d >= to %d", from, to) @@ -176,14 +185,17 @@ func (db *ErigonDB) Prune(ctx context.Context, tx kv.RwTx, from, to uint64) erro return nil } +// Start starts the ErigonWorkingSetStore func (store *ErigonWorkingSetStore) Start(ctx context.Context) error { return nil } +// Stop stops the ErigonWorkingSetStore func (store *ErigonWorkingSetStore) Stop(ctx context.Context) error { return nil } +// FinalizeTx finalizes the transaction func (store *ErigonWorkingSetStore) FinalizeTx(ctx context.Context) error { blkCtx := protocol.MustGetBlockCtx(ctx) g := genesis.MustExtractGenesisContext(ctx) @@ -196,6 +208,7 @@ func (store *ErigonWorkingSetStore) FinalizeTx(ctx context.Context) error { return store.intraBlockState.FinalizeTx(rules, erigonstate.NewNoopWriter()) } +// Finalize finalizes the ErigonWorkingSetStore func (store *ErigonWorkingSetStore) Finalize(ctx context.Context) error { return nil } @@ -243,6 +256,7 @@ func (store *ErigonWorkingSetStore) prepareCommit(ctx context.Context, tx kv.RwT return store.db.Prune(ctx, tx, from, to) } +// Commit commits the ErigonWorkingSetStore func (store *ErigonWorkingSetStore) Commit(ctx context.Context, retention uint64) error { defer store.tx.Rollback() // BeginRw accounting for the context Done signal @@ -262,21 +276,26 @@ func (store *ErigonWorkingSetStore) Commit(ctx context.Context, retention uint64 return nil } +// Close closes the ErigonWorkingSetStore func (store *ErigonWorkingSetStore) Close() { store.tx.Rollback() } +// Snapshot creates a snapshot of the ErigonWorkingSetStore func (store *ErigonWorkingSetStore) Snapshot() int { return store.intraBlockState.Snapshot() } +// RevertSnapshot reverts the ErigonWorkingSetStore to a snapshot func (store *ErigonWorkingSetStore) RevertSnapshot(sn int) error { store.intraBlockState.RevertToSnapshot(sn) return nil } +// ResetSnapshots resets the snapshots of the ErigonWorkingSetStore func (store *ErigonWorkingSetStore) ResetSnapshots() {} +// PutObject puts an object into the ErigonWorkingSetStore func (store *ErigonWorkingSetStore) PutObject(ns string, key []byte, obj any) (err error) { storage := ObjectContractStorage(obj) if storage == nil { @@ -287,6 +306,7 @@ func (store *ErigonWorkingSetStore) PutObject(ns string, key []byte, obj any) (e return storage.StoreToContract(ns, key, store.newContractBackend(store.ctx, store.intraBlockState, store.sr)) } +// GetObject gets an object from the ErigonWorkingSetStore func (store *ErigonWorkingSetStore) GetObject(ns string, key []byte, obj any) error { storage := ObjectContractStorage(obj) if storage == nil { @@ -299,6 +319,7 @@ func (store *ErigonWorkingSetStore) GetObject(ns string, key []byte, obj any) er return storage.LoadFromContract(ns, key, store.newContractBackend(store.ctx, store.intraBlockState, store.sr)) } +// DeleteObject deletes an object from the ErigonWorkingSetStore func (store *ErigonWorkingSetStore) DeleteObject(ns string, key []byte, obj any) error { storage := ObjectContractStorage(obj) if storage == nil { @@ -309,6 +330,7 @@ func (store *ErigonWorkingSetStore) DeleteObject(ns string, key []byte, obj any) return storage.DeleteFromContract(ns, key, store.newContractBackend(store.ctx, store.intraBlockState, store.sr)) } +// States gets multiple objects from the ErigonWorkingSetStore func (store *ErigonWorkingSetStore) States(ns string, keys [][]byte, obj any) ([][]byte, [][]byte, error) { storage := ObjectContractStorage(obj) if storage == nil { @@ -354,17 +376,20 @@ func (store *ErigonWorkingSetStore) States(ns string, keys [][]byte, obj any) ([ return keys, results, nil } +// Digest returns the digest of the ErigonWorkingSetStore func (store *ErigonWorkingSetStore) Digest() hash.Hash256 { return hash.ZeroHash256 } +// CreateGenesisStates creates the genesis states in the ErigonWorkingSetStore func (store *ErigonWorkingSetStore) CreateGenesisStates(ctx context.Context) error { return systemcontracts.DeploySystemContractsIfNotExist(store.newContractBackend(ctx, store.intraBlockState, store.sr)) } -func (store *ErigonDB) Height() (uint64, error) { +// Height returns the current height of the ErigonDB +func (db *ErigonDB) Height() (uint64, error) { var height uint64 - err := store.rw.View(context.Background(), func(tx kv.Tx) error { + err := db.rw.View(context.Background(), func(tx kv.Tx) error { heightBytes, err := tx.GetOne(systemNS, heightKey) if err != nil { return errors.Wrap(err, "failed to get height from erigon working set store") @@ -383,24 +408,32 @@ func (store *ErigonDB) Height() (uint64, error) { return height, nil } -func (store *ErigonWorkingSetStore) newContractBackend(ctx context.Context, intraBlockState *erigonstate.IntraBlockState, sr erigonstate.StateReader) *contractBacked { +func (store *ErigonWorkingSetStore) newContractBackend(ctx context.Context, intraBlockState *erigonstate.IntraBlockState, sr erigonstate.StateReader) *contractBackend { blkCtx := protocol.MustGetBlockCtx(ctx) g, ok := genesis.ExtractGenesisContext(ctx) if !ok { log.S().Panic("failed to extract genesis context from block context") } bcCtx := protocol.MustGetBlockchainCtx(ctx) - return NewContractBackend(store.intraBlockState, store.sr, blkCtx.BlockHeight, blkCtx.BlockTimeStamp, &g, bcCtx.EvmNetworkID) + return NewContractBackend(store.intraBlockState, store.sr, blkCtx.BlockHeight, blkCtx.BlockTimeStamp, blkCtx.Producer, &g, bcCtx.EvmNetworkID) } +// KVStore returns nil as ErigonWorkingSetStore does not implement KVStore func (store *ErigonWorkingSetStore) KVStore() db.KVStore { return nil } +// IntraBlockState returns the intraBlockState of the ErigonWorkingSetStore func (store *ErigonWorkingSetStore) IntraBlockState() *erigonstate.IntraBlockState { return store.intraBlockState } +// StateReader returns the state reader of the ErigonWorkingSetStore +func (store *ErigonWorkingSetStore) StateReader() erigonstate.StateReader { + return store.sr +} + +// ObjectContractStorage returns the ContractStorage interface for the given object func ObjectContractStorage(obj any) ContractStorage { if cs, ok := obj.(ContractStorage); ok { return cs From 134cbdc8c0fea5d44b23327efcbb278e3649bcfa Mon Sep 17 00:00:00 2001 From: envestcc Date: Mon, 15 Sep 2025 12:00:54 +0800 Subject: [PATCH 18/26] address comment --- state/factory/erigonstore/contract_backend.go | 6 ++++- systemcontracts/namespace_storage.go | 27 ++++--------------- systemcontracts/systemcontracts.go | 10 +++++++ 3 files changed, 20 insertions(+), 23 deletions(-) diff --git a/state/factory/erigonstore/contract_backend.go b/state/factory/erigonstore/contract_backend.go index 9be1a98a71..e75f6d8432 100644 --- a/state/factory/erigonstore/contract_backend.go +++ b/state/factory/erigonstore/contract_backend.go @@ -49,6 +49,10 @@ type ( // NewContractBackend creates a new contract backend for system contract interaction func NewContractBackend(intraBlockState *erigonstate.IntraBlockState, org erigonstate.StateReader, height uint64, timestamp time.Time, producer address.Address, g *genesis.Genesis, evmNetworkID uint32) *contractBackend { + var producerAddr erigonComm.Address + if producer != nil { + producerAddr = erigonComm.BytesToAddress(producer.Bytes()) + } return &contractBackend{ intraBlockState: intraBlockState, org: org, @@ -56,7 +60,7 @@ func NewContractBackend(intraBlockState *erigonstate.IntraBlockState, org erigon timestamp: timestamp, g: g, evmNetworkID: evmNetworkID, - producer: erigonComm.BytesToAddress(producer.Bytes()), + producer: producerAddr, } } diff --git a/systemcontracts/namespace_storage.go b/systemcontracts/namespace_storage.go index 909d542a61..72320b8058 100644 --- a/systemcontracts/namespace_storage.go +++ b/systemcontracts/namespace_storage.go @@ -16,30 +16,16 @@ import ( // NamespaceGenericValue represents the value structure in the NamespaceStorage contract // This is the same as GenericValue but renamed to avoid conflicts -type NamespaceGenericValue struct { - PrimaryData []byte `json:"primaryData"` - SecondaryData []byte `json:"secondaryData"` - AuxiliaryData []byte `json:"auxiliaryData"` -} +type NamespaceGenericValue = GenericValue // NamespaceBatchGetResult represents the result of a batch get operation -type NamespaceBatchGetResult struct { - Values []NamespaceGenericValue `json:"values"` - ExistsFlags []bool `json:"existsFlags"` -} +type NamespaceBatchGetResult = BatchGetResult // NamespaceListResult represents the result of a list operation -type NamespaceListResult struct { - KeyList [][]byte `json:"keyList"` - Values []NamespaceGenericValue `json:"values"` - Total *big.Int `json:"total"` -} +type NamespaceListResult = ListResult // NamespaceListKeysResult represents the result of a listKeys operation -type NamespaceListKeysResult struct { - KeyList [][]byte `json:"keyList"` - Total *big.Int `json:"total"` -} +type NamespaceListKeysResult = ListKeysResult // NamespaceListNamespacesResult represents the result of a listNamespaces operation type NamespaceListNamespacesResult struct { @@ -49,10 +35,7 @@ type NamespaceListNamespacesResult struct { } // NamespaceGetResult represents the result of a get operation -type NamespaceGetResult struct { - Value NamespaceGenericValue `json:"value"` - KeyExists bool `json:"keyExists"` -} +type NamespaceGetResult = GetResult // NamespaceStorageContract provides an interface to interact with the NamespaceStorage smart contract type NamespaceStorageContract struct { diff --git a/systemcontracts/systemcontracts.go b/systemcontracts/systemcontracts.go index 2e8e1a1a8d..19b0e62803 100644 --- a/systemcontracts/systemcontracts.go +++ b/systemcontracts/systemcontracts.go @@ -68,6 +68,7 @@ var systemContractTypes = map[int]int{ // SystemContracts holds all system contracts var SystemContracts []SystemContract +// systemContractCreatorAddr is the address used to create system contracts var systemContractCreatorAddr = hash.Hash160b([]byte("system_contract_creator")) func init() { @@ -105,6 +106,15 @@ func initSystemContracts() { } } +// SystemContractCreatorAddr returns the address used to create system contracts +func SystemContractCreatorAddr() address.Address { + addr, err := address.FromBytes(systemContractCreatorAddr[:]) + if err != nil { + log.S().Panic("Invalid system contract creator address: " + err.Error()) + } + return addr +} + // ContractBackend defines the interface for contract backend operations type ContractBackend interface { Call(callMsg *ethereum.CallMsg) ([]byte, error) From 151654e8fbd53cea946741ada83d2f04ccbb366e Mon Sep 17 00:00:00 2001 From: zhi Date: Wed, 17 Sep 2025 14:43:42 +0800 Subject: [PATCH 19/26] refactor --- go.mod | 2 +- state/account.go | 34 ---- state/factory/erigonstore/accountstorage.go | 129 ++++++++++++++ state/factory/erigonstore/contract_backend.go | 99 ++--------- state/factory/erigonstore/contract_storage.go | 31 ---- .../contract_storage_namespaced.go | 134 -------------- .../erigonstore/contract_storage_standard.go | 129 -------------- state/factory/erigonstore/objectstorage.go | 86 +++++++++ .../factory/erigonstore}/systemcontracts.go | 85 ++------- .../erigonstore/workingsetstore_erigon.go | 164 +++++++++--------- state/factory/workingset.go | 9 +- state/factory/workingsetstore.go | 15 +- .../workingsetstore_erigon_simulate.go | 21 ++- state/factory/workingsetstore_test.go | 34 +++- .../factory/workingsetstore_with_secondary.go | 7 +- state/state.go | 9 - systemcontracts/generic_storage.go | 52 ++---- systemcontracts/namespace_storage.go | 30 ++-- systemcontracts/namespace_storage_wrapper.go | 85 +++++++++ systemcontracts/storage.go | 114 ++++++++++++ 20 files changed, 616 insertions(+), 653 deletions(-) create mode 100644 state/factory/erigonstore/accountstorage.go delete mode 100644 state/factory/erigonstore/contract_storage.go delete mode 100644 state/factory/erigonstore/contract_storage_namespaced.go delete mode 100644 state/factory/erigonstore/contract_storage_standard.go create mode 100644 state/factory/erigonstore/objectstorage.go rename {systemcontracts => state/factory/erigonstore}/systemcontracts.go (50%) create mode 100644 systemcontracts/namespace_storage_wrapper.go create mode 100644 systemcontracts/storage.go diff --git a/go.mod b/go.mod index aa23e34054..e096d2e99a 100644 --- a/go.mod +++ b/go.mod @@ -241,7 +241,7 @@ require ( github.com/go-logr/logr v1.4.2 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/go-ole/go-ole v1.3.0 // indirect - github.com/gogo/protobuf v1.3.2 // indirect + github.com/gogo/protobuf v1.3.2 github.com/golang-jwt/jwt v3.2.2+incompatible // indirect github.com/golang/protobuf v1.5.4 // indirect github.com/google/gopacket v1.1.19 // indirect diff --git a/state/account.go b/state/account.go index d0f4f07e9f..9341432015 100644 --- a/state/account.go +++ b/state/account.go @@ -9,7 +9,6 @@ import ( "math/big" "github.com/iotexproject/go-pkgs/hash" - "github.com/iotexproject/iotex-address/address" "github.com/pkg/errors" "google.golang.org/protobuf/proto" @@ -272,39 +271,6 @@ func (st *Account) Clone() *Account { return &s } -func (st *Account) StoreToContract(ns string, key []byte, backend ContractBackend) error { - addr, err := address.FromBytes(key) - if err != nil { - return errors.Wrapf(err, "failed to convert key to address %x", key) - } - return backend.PutAccount(addr, st) -} - -func (st *Account) LoadFromContract(ns string, key []byte, backend ContractBackend) error { - addr, err := address.FromBytes(key) - if err != nil { - return errors.Wrapf(err, "failed to convert key to address %x", key) - } - acc, err := backend.Account(addr) - if err != nil { - return err - } - *st = *acc - return nil -} - -func (st *Account) DeleteFromContract(ns string, key []byte, backend ContractBackend) error { - return errors.New("not implemented") -} - -func (st *Account) ListFromContract(ns string, backend ContractBackend) ([][]byte, []any, error) { - return nil, nil, errors.New("not implemented") -} - -func (st *Account) BatchFromContract(ns string, keys [][]byte, backend ContractBackend) ([]any, error) { - return nil, errors.New("not implemented") -} - // NewAccount creates a new account with options func NewAccount(opts ...AccountCreationOption) (*Account, error) { account := &Account{ diff --git a/state/factory/erigonstore/accountstorage.go b/state/factory/erigonstore/accountstorage.go new file mode 100644 index 0000000000..a587b30559 --- /dev/null +++ b/state/factory/erigonstore/accountstorage.go @@ -0,0 +1,129 @@ +package erigonstore + +import ( + erigonComm "github.com/erigontech/erigon-lib/common" + "github.com/erigontech/erigon/core/types/accounts" + "github.com/ethereum/go-ethereum/common" + "github.com/gogo/protobuf/proto" + "github.com/holiman/uint256" + "github.com/pkg/errors" + + "github.com/iotexproject/iotex-core/v2/action/protocol/account/accountpb" + "github.com/iotexproject/iotex-core/v2/state" + "github.com/iotexproject/iotex-core/v2/systemcontracts" +) + +type accountStorage struct { + backend *contractBackend + contract systemcontracts.StorageContract +} + +func newAccountStorage(addr common.Address, backend *contractBackend) (*accountStorage, error) { + contract, err := systemcontracts.NewGenericStorageContract( + addr, + backend, + ) + if err != nil { + return nil, errors.Wrap(err, "failed to create account storage contract") + } + return &accountStorage{ + backend: backend, + contract: contract, + }, nil +} + +func (as *accountStorage) Delete([]byte) error { + return errors.New("not implemented") +} + +func (as *accountStorage) Batch([][]byte) (state.Iterator, error) { + return nil, errors.New("not implemented") +} + +func (as *accountStorage) List() (state.Iterator, error) { + return nil, errors.New("not implemented") +} + +func (as *accountStorage) Load(key []byte, obj any) error { + addr := erigonComm.BytesToAddress(key) + acct, ok := obj.(*state.Account) + if !ok { + return errors.New("obj is not of type *state.Account") + } + if !as.backend.intraBlockState.Exist(addr) { + return errors.Wrapf(state.ErrStateNotExist, "address: %x", addr.Bytes()) + } + // load other fields from the account storage contract + value, err := as.contract.Get(addr.Bytes()) + if err != nil { + return errors.Wrapf(err, "failed to get account data for address %x", addr.Bytes()) + } + if !value.KeyExists { + return errors.Errorf("account info not found for address %x", addr.Bytes()) + } + pbAcc := &accountpb.Account{} + if err := proto.Unmarshal(value.Value.PrimaryData, pbAcc); err != nil { + return errors.Wrapf(err, "failed to unmarshal account data for address %x", addr.Bytes()) + } + + balance := as.backend.intraBlockState.GetBalance(addr) + nonce := as.backend.intraBlockState.GetNonce(addr) + pbAcc.Balance = balance.String() + switch pbAcc.Type { + case accountpb.AccountType_ZERO_NONCE: + pbAcc.Nonce = nonce + case accountpb.AccountType_DEFAULT: + pbAcc.Nonce = nonce - 1 + default: + return errors.Errorf("unknown account type %v for address %x", pbAcc.Type, addr.Bytes()) + } + + if ch := as.backend.intraBlockState.GetCodeHash(addr); !accounts.IsEmptyCodeHash(ch) { + pbAcc.CodeHash = ch.Bytes() + } + acct.FromProto(pbAcc) + return nil +} + +func (as *accountStorage) Exists(key []byte) (bool, error) { + return as.exists(key) +} + +func (as *accountStorage) exists(key []byte) (bool, error) { + addr := erigonComm.BytesToAddress(key) + if !as.backend.intraBlockState.Exist(addr) { + return false, nil + } + return true, nil +} + +func (as *accountStorage) Store(key []byte, value any) error { + if value == nil { + return errors.New("value is nil") + } + acc, ok := value.(*state.Account) + if !ok { + return errors.New("value is not of type *state.Account") + } + addr := erigonComm.BytesToAddress(key) + if !as.backend.intraBlockState.Exist(addr) { + as.backend.intraBlockState.CreateAccount(addr, acc.IsContract()) + } + as.backend.intraBlockState.SetBalance(addr, uint256.MustFromBig(acc.Balance)) + nonce := acc.PendingNonce() + if as.backend.useZeroNonceForFreshAccount { + nonce = acc.PendingNonceConsideringFreshAccount() + } + as.backend.intraBlockState.SetNonce(addr, nonce) + // store other fields in the account storage contract + pbAcc := acc.ToProto() + pbAcc.Balance = "" + pbAcc.Nonce = 0 + pbAcc.CodeHash = nil + data, err := proto.Marshal(pbAcc) + if err != nil { + return errors.Wrapf(err, "failed to marshal account %x", addr.Bytes()) + } + + return as.contract.Put(key, systemcontracts.GenericValue{PrimaryData: data}) +} diff --git a/state/factory/erigonstore/contract_backend.go b/state/factory/erigonstore/contract_backend.go index e75f6d8432..e33beebae9 100644 --- a/state/factory/erigonstore/contract_backend.go +++ b/state/factory/erigonstore/contract_backend.go @@ -10,27 +10,21 @@ import ( "github.com/erigontech/erigon-lib/chain" erigonComm "github.com/erigontech/erigon-lib/common" erigonstate "github.com/erigontech/erigon/core/state" - "github.com/erigontech/erigon/core/types/accounts" erigonAcc "github.com/erigontech/erigon/core/types/accounts" "github.com/erigontech/erigon/core/vm" "github.com/erigontech/erigon/core/vm/evmtypes" "github.com/ethereum/go-ethereum" - "github.com/ethereum/go-ethereum/common" "github.com/holiman/uint256" "github.com/pkg/errors" "go.uber.org/zap" - "google.golang.org/protobuf/proto" "github.com/iotexproject/iotex-address/address" "github.com/iotexproject/iotex-core/v2/action/protocol" - "github.com/iotexproject/iotex-core/v2/action/protocol/account/accountpb" "github.com/iotexproject/iotex-core/v2/action/protocol/execution/evm" iotexevm "github.com/iotexproject/iotex-core/v2/action/protocol/execution/evm" "github.com/iotexproject/iotex-core/v2/blockchain/genesis" "github.com/iotexproject/iotex-core/v2/pkg/log" - "github.com/iotexproject/iotex-core/v2/state" - "github.com/iotexproject/iotex-core/v2/systemcontracts" ) type ( @@ -44,23 +38,26 @@ type ( producer erigonComm.Address g *genesis.Genesis evmNetworkID uint32 + + useZeroNonceForFreshAccount bool } ) // NewContractBackend creates a new contract backend for system contract interaction -func NewContractBackend(intraBlockState *erigonstate.IntraBlockState, org erigonstate.StateReader, height uint64, timestamp time.Time, producer address.Address, g *genesis.Genesis, evmNetworkID uint32) *contractBackend { +func NewContractBackend(intraBlockState *erigonstate.IntraBlockState, org erigonstate.StateReader, height uint64, timestamp time.Time, producer address.Address, g *genesis.Genesis, evmNetworkID uint32, useZeroNonceForFreshAccount bool) *contractBackend { var producerAddr erigonComm.Address if producer != nil { producerAddr = erigonComm.BytesToAddress(producer.Bytes()) } return &contractBackend{ - intraBlockState: intraBlockState, - org: org, - height: height, - timestamp: timestamp, - g: g, - evmNetworkID: evmNetworkID, - producer: producerAddr, + intraBlockState: intraBlockState, + org: org, + height: height, + timestamp: timestamp, + g: g, + evmNetworkID: evmNetworkID, + producer: producerAddr, + useZeroNonceForFreshAccount: useZeroNonceForFreshAccount, } } @@ -107,80 +104,6 @@ func (backend *contractBackend) Exists(addr address.Address) bool { return backend.intraBlockState.Exist(erigonComm.BytesToAddress(addr.Bytes())) } -func (backend *contractBackend) PutAccount(_addr address.Address, acc *state.Account) error { - addr := erigonComm.BytesToAddress(_addr.Bytes()) - if !backend.intraBlockState.Exist(addr) { - backend.intraBlockState.CreateAccount(addr, acc.IsContract()) - } - backend.intraBlockState.SetBalance(addr, uint256.MustFromBig(acc.Balance)) - ctx := protocol.WithFeatureCtx(protocol.WithBlockCtx(genesis.WithGenesisContext(context.Background(), *backend.g), protocol.BlockCtx{BlockHeight: backend.height})) - fCtx := protocol.MustGetFeatureCtx(ctx) - nonce := acc.PendingNonce() - if fCtx.UseZeroNonceForFreshAccount { - nonce = acc.PendingNonceConsideringFreshAccount() - } - backend.intraBlockState.SetNonce(addr, nonce) - // store other fields in the account storage contract - pbAcc := acc.ToProto() - pbAcc.Balance = "" - pbAcc.Nonce = 0 - data, err := proto.Marshal(pbAcc) - if err != nil { - return errors.Wrapf(err, "failed to marshal account %x", addr.Bytes()) - } - contract, err := systemcontracts.NewGenericStorageContract(backend.accountContractAddr(), backend) - if err != nil { - return errors.Wrapf(err, "failed to create account storage contract for address %x", addr.Bytes()) - } - return contract.Put(_addr.Bytes(), systemcontracts.GenericValue{PrimaryData: data}) -} - -func (backend *contractBackend) Account(_addr address.Address) (*state.Account, error) { - addr := erigonComm.BytesToAddress(_addr.Bytes()) - if !backend.intraBlockState.Exist(addr) { - return nil, errors.Wrapf(state.ErrStateNotExist, "address: %x", addr.Bytes()) - } - // load other fields from the account storage contract - contract, err := systemcontracts.NewGenericStorageContract(backend.accountContractAddr(), backend) - if err != nil { - return nil, errors.Wrapf(err, "failed to create account storage contract for address %x", addr.Bytes()) - } - value, err := contract.Get(_addr.Bytes()) - if err != nil { - return nil, errors.Wrapf(err, "failed to get account data for address %x", addr.Bytes()) - } - if !value.KeyExists { - return nil, errors.Errorf("account info not found for address %x", addr.Bytes()) - } - pbAcc := &accountpb.Account{} - if err := proto.Unmarshal(value.Value.PrimaryData, pbAcc); err != nil { - return nil, errors.Wrapf(err, "failed to unmarshal account data for address %x", addr.Bytes()) - } - - balance := backend.intraBlockState.GetBalance(addr) - nonce := backend.intraBlockState.GetNonce(addr) - pbAcc.Balance = balance.String() - switch pbAcc.Type { - case accountpb.AccountType_ZERO_NONCE: - pbAcc.Nonce = nonce - case accountpb.AccountType_DEFAULT: - pbAcc.Nonce = nonce - 1 - default: - return nil, errors.Errorf("unknown account type %v for address %x", pbAcc.Type, addr.Bytes()) - } - - if ch := backend.intraBlockState.GetCodeHash(addr); !accounts.IsEmptyCodeHash(ch) { - pbAcc.CodeHash = ch.Bytes() - } - acc := &state.Account{} - acc.FromProto(pbAcc) - return acc, nil -} - -func (backend *contractBackend) accountContractAddr() common.Address { - return common.BytesToAddress(systemcontracts.SystemContracts[systemcontracts.AccountInfoContractIndex].Address.Bytes()) -} - func (backend *contractBackend) prepare(intra evmtypes.IntraBlockState) (*vm.EVM, error) { blkCtxE := evmtypes.BlockContext{ CanTransfer: func(state evmtypes.IntraBlockState, addr erigonComm.Address, amount *uint256.Int) bool { diff --git a/state/factory/erigonstore/contract_storage.go b/state/factory/erigonstore/contract_storage.go deleted file mode 100644 index ae8c57d25a..0000000000 --- a/state/factory/erigonstore/contract_storage.go +++ /dev/null @@ -1,31 +0,0 @@ -package erigonstore - -import ( - "github.com/iotexproject/iotex-address/address" - - "github.com/iotexproject/iotex-core/v2/state" -) - -type ContractBackend = state.ContractBackend - -// ContractStorage defines the interface for contract storage operations -type ContractStorage interface { - StoreToContract(ns string, key []byte, backend ContractBackend) error - LoadFromContract(ns string, key []byte, backend ContractBackend) error - DeleteFromContract(ns string, key []byte, backend ContractBackend) error - ListFromContract(ns string, backend ContractBackend) ([][]byte, []any, error) - BatchFromContract(ns string, keys [][]byte, backend ContractBackend) ([]any, error) -} - -// ContractStorageStandard defines the interface for standard contract storage operations -type ContractStorageStandard interface { - ContractStorageAddress(ns string) (address.Address, error) - New() ContractStorageStandard - Serialize() ([]byte, error) - Deserialize([]byte) error -} - -// ContractStorageProxy defines the interface for contract storage proxy operations -type ContractStorageProxy interface { - ContractStorageProxy() ContractStorage -} diff --git a/state/factory/erigonstore/contract_storage_namespaced.go b/state/factory/erigonstore/contract_storage_namespaced.go deleted file mode 100644 index 32b1759b92..0000000000 --- a/state/factory/erigonstore/contract_storage_namespaced.go +++ /dev/null @@ -1,134 +0,0 @@ -package erigonstore - -import ( - "math/big" - - "github.com/ethereum/go-ethereum/common" - "github.com/pkg/errors" - - "github.com/iotexproject/iotex-core/v2/pkg/log" - "github.com/iotexproject/iotex-core/v2/state" - "github.com/iotexproject/iotex-core/v2/systemcontracts" -) - -type contractStorageNamespacedWrapper struct { - standard ContractStorageStandard -} - -// NewContractStorageNamespacedWrapper creates a new ContractStorage wrapper for namespaced storage -func NewContractStorageNamespacedWrapper(standard ContractStorageStandard) ContractStorage { - return &contractStorageNamespacedWrapper{standard: standard} -} - -func (cs *contractStorageNamespacedWrapper) StoreToContract(ns string, key []byte, backend ContractBackend) error { - contract, err := cs.storageContract(ns, backend) - if err != nil { - return err - } - data, err := cs.standard.Serialize() - if err != nil { - return errors.Wrap(err, "failed to serialize storage standard") - } - if err := contract.Put(ns, key, systemcontracts.NamespaceGenericValue{PrimaryData: data}); err != nil { - return errors.Wrapf(err, "failed to store storage standard to contract %s", contract.Address().Hex()) - } - log.S().Debugf("Stored storage standard to contract %s with key %x, value: %+v", contract.Address().Hex(), key, cs.standard) - return nil -} - -func (cs *contractStorageNamespacedWrapper) LoadFromContract(ns string, key []byte, backend ContractBackend) error { - contract, err := cs.storageContract(ns, backend) - if err != nil { - return err - } - value, err := contract.Get(ns, key) - if err != nil { - return errors.Wrapf(err, "failed to get storage standard from contract %s with key %x", contract.Address().Hex(), key) - } - if !value.KeyExists { - return errors.Wrapf(state.ErrStateNotExist, "storage standard does not exist in contract %s with key %x", contract.Address().Hex(), key) - } - if err := cs.standard.Deserialize(value.Value.PrimaryData); err != nil { - return errors.Wrap(err, "failed to deserialize storage standard") - } - log.S().Debugf("Loaded storage standard from contract %s with key %x, value: %+v", contract.Address().Hex(), key, cs.standard) - return nil -} - -func (cs *contractStorageNamespacedWrapper) DeleteFromContract(ns string, key []byte, backend ContractBackend) error { - contract, err := cs.storageContract(ns, backend) - if err != nil { - return err - } - if err := contract.Remove(ns, key); err != nil { - return errors.Wrapf(err, "failed to delete storage standard from contract %s with key %x", contract.Address().Hex(), key) - } - log.S().Debugf("Deleted storage standard from contract %s with key %x", contract.Address().Hex(), key) - return nil -} - -func (cs *contractStorageNamespacedWrapper) ListFromContract(ns string, backend ContractBackend) ([][]byte, []any, error) { - contract, err := cs.storageContract(ns, backend) - if err != nil { - return nil, nil, err - } - count, err := contract.CountInNamespace(ns) - if err != nil { - return nil, nil, errors.Wrapf(err, "failed to count storage standards in contract %s", contract.Address().Hex()) - } - if count.Sign() == 0 { - return nil, nil, nil - } - listResult, err := contract.List(ns, big.NewInt(0), count) - if err != nil { - return nil, nil, errors.Wrapf(err, "failed to list storage standards from contract %s", contract.Address().Hex()) - } - log.S().Debugf("Listed storage standards from contract %s with keys %v", contract.Address().Hex(), listResult.KeyList) - var indices []any - for _, value := range listResult.Values { - bi := cs.standard.New() - if err := bi.Deserialize(value.PrimaryData); err != nil { - return nil, nil, errors.Wrapf(err, "failed to deserialize storage standard from contract %s", contract.Address().Hex()) - } - indices = append(indices, bi) - } - log.S().Debugf("Listed %d storage standards from contract %s", len(indices), contract.Address().Hex()) - return listResult.KeyList, indices, nil -} - -func (cs *contractStorageNamespacedWrapper) BatchFromContract(ns string, keys [][]byte, backend ContractBackend) ([]any, error) { - contract, err := cs.storageContract(ns, backend) - if err != nil { - return nil, err - } - storeResult, err := contract.BatchGet(ns, keys) - if err != nil { - return nil, errors.Wrap(err, "failed to batch get storage standards from contract") - } - results := make([]any, 0, len(storeResult.Values)) - for i, value := range storeResult.Values { - if !storeResult.ExistsFlags[i] { - results = append(results, nil) - continue - } - res := cs.standard.New() - if err := res.Deserialize(value.PrimaryData); err != nil { - return nil, errors.Wrapf(err, "failed to deserialize storage standard %x", keys[i]) - } - results = append(results, res) - } - log.S().Debugf("Batch loaded %d storage standard from contract %s with keys %d", len(results), contract.Address().Hex(), len(keys)) - return results, nil -} - -func (cs *contractStorageNamespacedWrapper) storageContract(ns string, backend ContractBackend) (*systemcontracts.NamespaceStorageContract, error) { - addr, err := cs.standard.ContractStorageAddress(ns) - if err != nil { - return nil, err - } - contract, err := systemcontracts.NewNamespaceStorageContract(common.BytesToAddress(addr.Bytes()), backend) - if err != nil { - return nil, errors.Wrapf(err, "failed to create block meta storage contract") - } - return contract, nil -} diff --git a/state/factory/erigonstore/contract_storage_standard.go b/state/factory/erigonstore/contract_storage_standard.go deleted file mode 100644 index 2cbec56565..0000000000 --- a/state/factory/erigonstore/contract_storage_standard.go +++ /dev/null @@ -1,129 +0,0 @@ -package erigonstore - -import ( - "github.com/ethereum/go-ethereum/common" - "github.com/pkg/errors" - - "github.com/iotexproject/iotex-core/v2/pkg/log" - "github.com/iotexproject/iotex-core/v2/state" - "github.com/iotexproject/iotex-core/v2/systemcontracts" -) - -type contractStorageStandardWrapper struct { - standard ContractStorageStandard -} - -// NewContractStorageStandardWrapper creates a new ContractStorage wrapper for standard storage -func NewContractStorageStandardWrapper(standard ContractStorageStandard) ContractStorage { - return &contractStorageStandardWrapper{standard: standard} -} - -func (cs *contractStorageStandardWrapper) StoreToContract(ns string, key []byte, backend ContractBackend) error { - contract, err := cs.storageContract(ns, backend) - if err != nil { - return err - } - data, err := cs.standard.Serialize() - if err != nil { - return errors.Wrap(err, "failed to serialize storage standard") - } - if err := contract.Put(key, systemcontracts.GenericValue{PrimaryData: data}); err != nil { - return errors.Wrapf(err, "failed to store storage standard to contract %s", contract.Address().Hex()) - } - return nil -} - -func (cs *contractStorageStandardWrapper) LoadFromContract(ns string, key []byte, backend ContractBackend) error { - contract, err := cs.storageContract(ns, backend) - if err != nil { - return err - } - value, err := contract.Get(key) - if err != nil { - return errors.Wrapf(err, "failed to get storage standard from contract %s with key %x", contract.Address().Hex(), key) - } - if !value.KeyExists { - return errors.Wrapf(state.ErrStateNotExist, "storage standard does not exist in contract %s with key %x", contract.Address().Hex(), key) - } - if err := cs.standard.Deserialize(value.Value.PrimaryData); err != nil { - return errors.Wrap(err, "failed to deserialize storage standard") - } - return nil -} - -func (cs *contractStorageStandardWrapper) DeleteFromContract(ns string, key []byte, backend ContractBackend) error { - contract, err := cs.storageContract(ns, backend) - if err != nil { - return err - } - if err := contract.Remove(key); err != nil { - return errors.Wrapf(err, "failed to delete storage standard from contract %s with key %x", contract.Address().Hex(), key) - } - return nil -} - -func (cs *contractStorageStandardWrapper) ListFromContract(ns string, backend ContractBackend) ([][]byte, []any, error) { - contract, err := cs.storageContract(ns, backend) - if err != nil { - return nil, nil, err - } - count, err := contract.Count() - if err != nil { - return nil, nil, errors.Wrapf(err, "failed to count storage standards in contract %s", contract.Address().Hex()) - } - if count.Sign() == 0 { - return nil, nil, nil - } - listResult, err := contract.List(0, count.Uint64()) - if err != nil { - return nil, nil, errors.Wrapf(err, "failed to list storage standards from contract %s", contract.Address().Hex()) - } - log.S().Debugf("Listed storage standards from contract %s with keys %v", contract.Address().Hex(), listResult.KeyList) - var indices []any - for _, value := range listResult.Values { - bi := cs.standard.New() - if err := bi.Deserialize(value.PrimaryData); err != nil { - return nil, nil, errors.Wrapf(err, "failed to deserialize storage standard from contract %s", contract.Address().Hex()) - } - indices = append(indices, bi) - } - log.S().Debugf("Listed %d storage standards from contract %s", len(indices), contract.Address().Hex()) - return listResult.KeyList, indices, nil -} - -func (cs *contractStorageStandardWrapper) BatchFromContract(ns string, keys [][]byte, backend ContractBackend) ([]any, error) { - contract, err := cs.storageContract(ns, backend) - if err != nil { - return nil, err - } - storeResult, err := contract.BatchGet(keys) - if err != nil { - return nil, errors.Wrap(err, "failed to batch get storage standards from contract") - } - results := make([]any, 0, len(storeResult.Values)) - for i, value := range storeResult.Values { - if !storeResult.ExistsFlags[i] { - results = append(results, nil) - continue - } - res := cs.standard.New() - if err := res.Deserialize(value.PrimaryData); err != nil { - return nil, errors.Wrapf(err, "failed to deserialize storage standard %x", keys[i]) - } - results = append(results, res) - } - log.S().Debugf("Batch loaded %d storage standard from contract %s with keys %d", len(results), contract.Address().Hex(), len(keys)) - return results, nil -} - -func (cs *contractStorageStandardWrapper) storageContract(ns string, backend ContractBackend) (*systemcontracts.GenericStorageContract, error) { - addr, err := cs.standard.ContractStorageAddress(ns) - if err != nil { - return nil, err - } - contract, err := systemcontracts.NewGenericStorageContract(common.BytesToAddress(addr.Bytes()), backend) - if err != nil { - return nil, errors.Wrapf(err, "failed to create block meta storage contract") - } - return contract, nil -} diff --git a/state/factory/erigonstore/objectstorage.go b/state/factory/erigonstore/objectstorage.go new file mode 100644 index 0000000000..dfc9a7a0b9 --- /dev/null +++ b/state/factory/erigonstore/objectstorage.go @@ -0,0 +1,86 @@ +package erigonstore + +import ( + "math/big" + + "github.com/pkg/errors" + + "github.com/iotexproject/iotex-core/v2/state" + "github.com/iotexproject/iotex-core/v2/systemcontracts" +) + +type ( + // ObjectStorage defines an interface of object storage + ObjectStorage interface { + Store(key []byte, obj any) error + Load(key []byte, obj any) error + Delete(key []byte) error + List() (state.Iterator, error) + Batch(keys [][]byte) (state.Iterator, error) + } + + contractObjectStorage struct { + contract systemcontracts.StorageContract + } +) + +func newContractObjectStorage(contract systemcontracts.StorageContract) *contractObjectStorage { + return &contractObjectStorage{ + contract: contract, + } +} + +func (cos *contractObjectStorage) Store(key []byte, obj any) error { + gvc, ok := obj.(systemcontracts.GenericValueContainer) + if !ok { + return errors.New("object does not implement GenericValueContainer") + } + value, err := gvc.Encode() + if err != nil { + return err + } + return cos.contract.Put(key, value) +} + +func (cos *contractObjectStorage) Load(key []byte, obj any) error { + gvc, ok := obj.(systemcontracts.GenericValueContainer) + if !ok { + return errors.New("object does not implement GenericValueContainer") + } + value, err := cos.contract.Get(key) + if err != nil { + return err + } + // TODO: handle value.KeyExists + return gvc.Decode(value.Value) +} + +func (cos *contractObjectStorage) Delete(key []byte) error { + return cos.contract.Remove(key) +} + +func (cos *contractObjectStorage) List() (state.Iterator, error) { + count, err := cos.contract.Count() + if err != nil { + return nil, err + } + retval, err := cos.contract.List(0, count.Uint64()) + if err != nil { + return nil, err + } + + return systemcontracts.NewGenericValueObjectIterator(retval.KeyList, retval.Values, nil) +} + +func (cos *contractObjectStorage) Batch(keys [][]byte) (state.Iterator, error) { + retval, err := cos.contract.BatchGet(keys) + if err != nil { + return nil, err + } + + return systemcontracts.NewGenericValueObjectIterator(keys, retval.Values, retval.ExistsFlags) +} + +func (cos *contractObjectStorage) Count() (*big.Int, error) { + return cos.contract.Count() +} diff --git a/systemcontracts/systemcontracts.go b/state/factory/erigonstore/systemcontracts.go similarity index 50% rename from systemcontracts/systemcontracts.go rename to state/factory/erigonstore/systemcontracts.go index 19b0e62803..6d34027d74 100644 --- a/systemcontracts/systemcontracts.go +++ b/state/factory/erigonstore/systemcontracts.go @@ -1,18 +1,15 @@ -// Package systemcontracts provides system contract management functionality -package systemcontracts +package erigonstore import ( "encoding/hex" - "fmt" - "math/big" + "log" - "github.com/ethereum/go-ethereum" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/crypto" + "github.com/erigontech/erigon-lib/common" + "github.com/erigontech/erigon-lib/crypto" "github.com/iotexproject/go-pkgs/hash" "github.com/iotexproject/iotex-address/address" - - "github.com/iotexproject/iotex-core/v2/pkg/log" + "github.com/iotexproject/iotex-core/v2/systemcontracts" + "github.com/pkg/errors" ) // SystemContract represents a system contract with its address and bytecode @@ -65,32 +62,28 @@ var systemContractTypes = map[int]int{ StakingViewContractIndex: namespaceStorageContractType, } -// SystemContracts holds all system contracts -var SystemContracts []SystemContract +// systemContracts holds all system contracts +var systemContracts []SystemContract // systemContractCreatorAddr is the address used to create system contracts +// TODO: review and delete it var systemContractCreatorAddr = hash.Hash160b([]byte("system_contract_creator")) func init() { - initSystemContracts() -} - -// initSystemContracts initializes the system contracts array -func initSystemContracts() { - genericStorageByteCode, err := hex.DecodeString(GenericStorageByteCodeStr) + genericStorageByteCode, err := hex.DecodeString(systemcontracts.GenericStorageByteCodeStr) if err != nil { - log.S().Panic("failed to decode GenericStorageByteCode: " + err.Error()) + log.Panic(errors.Wrap(err, "failed to decode GenericStorageByteCode")) } - namespaceStorageByteCode, err := hex.DecodeString(NamespaceStorageContractByteCodeStr) + namespaceStorageByteCode, err := hex.DecodeString(systemcontracts.NamespaceStorageContractByteCodeStr) if err != nil { - log.S().Panic("failed to decode NamespaceStorageContractByteCode: " + err.Error()) + log.Panic(errors.Wrap(err, "failed to decode NamespaceStorageContractByteCode")) } - SystemContracts = make([]SystemContract, SystemContractCount) + systemContracts = make([]SystemContract, SystemContractCount) for i := 0; i < SystemContractCount; i++ { addr, err := address.FromBytes(crypto.CreateAddress(common.BytesToAddress(systemContractCreatorAddr[:]), uint64(i)).Bytes()) if err != nil { - log.S().Panic("Invalid system contract address: " + err.Error()) + log.Panic(errors.Wrap(err, "invalid system contract address")) } var byteCode []byte switch systemContractTypes[i] { @@ -99,55 +92,9 @@ func initSystemContracts() { default: byteCode = genericStorageByteCode } - SystemContracts[i] = SystemContract{ + systemContracts[i] = SystemContract{ Address: addr, Code: byteCode, } } } - -// SystemContractCreatorAddr returns the address used to create system contracts -func SystemContractCreatorAddr() address.Address { - addr, err := address.FromBytes(systemContractCreatorAddr[:]) - if err != nil { - log.S().Panic("Invalid system contract creator address: " + err.Error()) - } - return addr -} - -// ContractBackend defines the interface for contract backend operations -type ContractBackend interface { - Call(callMsg *ethereum.CallMsg) ([]byte, error) - Handle(callMsg *ethereum.CallMsg) error -} - -// ContractDeployer defines the interface for contract deployment operations -type ContractDeployer interface { - Deploy(callMsg *ethereum.CallMsg) (address.Address, error) - Exists(addr address.Address) bool -} - -// DeploySystemContractsIfNotExist deploys system contracts if they don't exist -func DeploySystemContractsIfNotExist(deployer ContractDeployer) error { - for idx, contract := range SystemContracts { - exists := deployer.Exists(contract.Address) - if !exists { - log.S().Infof("Deploying system contract [%d] %s", idx, contract.Address.String()) - msg := ðereum.CallMsg{ - From: common.BytesToAddress(systemContractCreatorAddr[:]), - Data: contract.Code, - Value: big.NewInt(0), - Gas: 10000000, - } - if addr, err := deployer.Deploy(msg); err != nil { - return fmt.Errorf("failed to deploy system contract %s: %w", contract.Address.String(), err) - } else if addr.String() != contract.Address.String() { - return fmt.Errorf("deployed contract address %s does not match expected address %s", addr.String(), contract.Address.String()) - } - log.S().Infof("System contract [%d] %s deployed successfully", idx, contract.Address.String()) - } else { - log.S().Infof("System contract [%d] %s already exists", idx, contract.Address.String()) - } - } - return nil -} diff --git a/state/factory/erigonstore/workingsetstore_erigon.go b/state/factory/erigonstore/workingsetstore_erigon.go index 18f77a9e4e..46cc5a828e 100644 --- a/state/factory/erigonstore/workingsetstore_erigon.go +++ b/state/factory/erigonstore/workingsetstore_erigon.go @@ -15,11 +15,14 @@ import ( "github.com/erigontech/erigon/eth/stagedsync" "github.com/erigontech/erigon/eth/stagedsync/stages" "github.com/erigontech/erigon/ethdb/prune" + "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/common" "github.com/holiman/uint256" "github.com/pkg/errors" "go.uber.org/zap" "github.com/iotexproject/go-pkgs/hash" + "github.com/iotexproject/iotex-address/address" "github.com/iotexproject/iotex-core/v2/action/protocol" "github.com/iotexproject/iotex-core/v2/action/protocol/execution/evm" @@ -46,11 +49,9 @@ type ErigonDB struct { // ErigonWorkingSetStore implements the Erigon working set store type ErigonWorkingSetStore struct { - db *ErigonDB - intraBlockState *erigonstate.IntraBlockState - tx kv.Tx - sr erigonstate.StateReader - ctx context.Context + db *ErigonDB + backend *contractBackend + tx kv.Tx } // NewErigonDB creates a new ErigonDB @@ -90,11 +91,9 @@ func (db *ErigonDB) NewErigonStore(ctx context.Context, height uint64) (*ErigonW r := erigonstate.NewPlainStateReader(tx) intraBlockState := erigonstate.New(r) return &ErigonWorkingSetStore{ - db: db, - tx: tx, - intraBlockState: intraBlockState, - sr: r, - ctx: ctx, + db: db, + tx: tx, + backend: newContractBackend(ctx, intraBlockState, r), }, nil } @@ -107,11 +106,9 @@ func (db *ErigonDB) NewErigonStoreDryrun(ctx context.Context, height uint64) (*E tsw := erigonstate.NewPlainState(tx, height, nil) intraBlockState := erigonstate.New(tsw) return &ErigonWorkingSetStore{ - db: db, - tx: tx, - intraBlockState: intraBlockState, - sr: tsw, - ctx: ctx, + db: db, + tx: tx, + backend: newContractBackend(ctx, intraBlockState, tsw), }, nil } @@ -205,7 +202,7 @@ func (store *ErigonWorkingSetStore) FinalizeTx(ctx context.Context) error { } chainRules := chainCfg.Rules(new(big.Int).SetUint64(blkCtx.BlockHeight), g.IsSumatra(blkCtx.BlockHeight), uint64(blkCtx.BlockTimeStamp.Unix())) rules := evm.NewErigonRules(&chainRules) - return store.intraBlockState.FinalizeTx(rules, erigonstate.NewNoopWriter()) + return store.backend.intraBlockState.FinalizeTx(rules, erigonstate.NewNoopWriter()) } // Finalize finalizes the ErigonWorkingSetStore @@ -227,7 +224,7 @@ func (store *ErigonWorkingSetStore) prepareCommit(ctx context.Context, tx kv.RwT rules := evm.NewErigonRules(&chainRules) tsw := erigonstate.NewPlainStateWriter(tx, tx, height) log.L().Debug("intraBlockState Commit block", zap.Uint64("height", height)) - err = store.intraBlockState.CommitBlock(rules, tsw) + err = store.backend.intraBlockState.CommitBlock(rules, tsw) if err != nil { return err } @@ -283,12 +280,12 @@ func (store *ErigonWorkingSetStore) Close() { // Snapshot creates a snapshot of the ErigonWorkingSetStore func (store *ErigonWorkingSetStore) Snapshot() int { - return store.intraBlockState.Snapshot() + return store.backend.intraBlockState.Snapshot() } // RevertSnapshot reverts the ErigonWorkingSetStore to a snapshot func (store *ErigonWorkingSetStore) RevertSnapshot(sn int) error { - store.intraBlockState.RevertToSnapshot(sn) + store.backend.intraBlockState.RevertToSnapshot(sn) return nil } @@ -297,18 +294,24 @@ func (store *ErigonWorkingSetStore) ResetSnapshots() {} // PutObject puts an object into the ErigonWorkingSetStore func (store *ErigonWorkingSetStore) PutObject(ns string, key []byte, obj any) (err error) { - storage := ObjectContractStorage(obj) + storage, err := store.NewObjectStorage(ns, obj) + if err != nil { + return err + } if storage == nil { // TODO: return error after all types are supported return nil } log.L().Debug("put object", zap.String("namespace", ns), log.Hex("key", key), zap.String("type", fmt.Sprintf("%T", obj)), zap.Any("content", obj)) - return storage.StoreToContract(ns, key, store.newContractBackend(store.ctx, store.intraBlockState, store.sr)) + return storage.Store(key, obj) } // GetObject gets an object from the ErigonWorkingSetStore func (store *ErigonWorkingSetStore) GetObject(ns string, key []byte, obj any) error { - storage := ObjectContractStorage(obj) + storage, err := store.NewObjectStorage(ns, obj) + if err != nil { + return err + } if storage == nil { // TODO: return error after all types are supported return nil @@ -316,64 +319,37 @@ func (store *ErigonWorkingSetStore) GetObject(ns string, key []byte, obj any) er defer func() { log.L().Debug("get object", zap.String("namespace", ns), log.Hex("key", key), zap.String("type", fmt.Sprintf("%T", obj))) }() - return storage.LoadFromContract(ns, key, store.newContractBackend(store.ctx, store.intraBlockState, store.sr)) + // return storage.LoadFromContract(ns, key, store.newContractBackend(store.ctx, store.intraBlockState, store.sr)) + return storage.Load(key, obj) } // DeleteObject deletes an object from the ErigonWorkingSetStore func (store *ErigonWorkingSetStore) DeleteObject(ns string, key []byte, obj any) error { - storage := ObjectContractStorage(obj) + storage, err := store.NewObjectStorage(ns, obj) + if err != nil { + return err + } if storage == nil { // TODO: return error after all types are supported return nil } log.L().Debug("delete object", zap.String("namespace", ns), log.Hex("key", key), zap.String("type", fmt.Sprintf("%T", obj))) - return storage.DeleteFromContract(ns, key, store.newContractBackend(store.ctx, store.intraBlockState, store.sr)) + return storage.Delete(key) } // States gets multiple objects from the ErigonWorkingSetStore -func (store *ErigonWorkingSetStore) States(ns string, keys [][]byte, obj any) ([][]byte, [][]byte, error) { - storage := ObjectContractStorage(obj) +func (store *ErigonWorkingSetStore) States(ns string, obj any, keys [][]byte) (state.Iterator, error) { + storage, err := store.NewObjectStorage(ns, obj) + if err != nil { + return nil, err + } if storage == nil { - return nil, nil, errors.Errorf("unsupported object type %T in ns %s", obj, ns) + return nil, errors.Errorf("unsupported object type %T in ns %s", obj, ns) } - var ( - objs []any - err error - results [][]byte - backend = store.newContractBackend(store.ctx, store.intraBlockState, store.sr) - ) if len(keys) == 0 { - keys, objs, err = storage.ListFromContract(ns, backend) - } else { - objs, err = storage.BatchFromContract(ns, keys, backend) - } - log.L().Debug("list objs from erigon working set store", - zap.String("ns", ns), - zap.Int("num", len(keys)), - zap.Int("objsize", len(objs)), - zap.String("obj", fmt.Sprintf("%T", obj)), - ) - if err != nil { - return nil, nil, errors.Wrapf(err, "failed to list objects from erigon working set store for namespace %s", ns) - } - for i, obj := range objs { - log.L().Debug("list obj from erigon working set store", - zap.String("ns", ns), - log.Hex("key", keys[i]), - zap.String("storage", fmt.Sprintf("%T", obj)), - zap.Any("content", obj), - ) - if obj == nil { - results = append(results, nil) - continue - } - res, err := state.Serialize(obj) - if err != nil { - return nil, nil, errors.Wrapf(err, "failed to serialize object for namespace %s and key %x", ns, keys[i]) - } - results = append(results, res) + return storage.List() } - return keys, results, nil + return storage.Batch(keys) } // Digest returns the digest of the ErigonWorkingSetStore @@ -382,8 +358,29 @@ func (store *ErigonWorkingSetStore) Digest() hash.Hash256 { } // CreateGenesisStates creates the genesis states in the ErigonWorkingSetStore -func (store *ErigonWorkingSetStore) CreateGenesisStates(ctx context.Context) error { - return systemcontracts.DeploySystemContractsIfNotExist(store.newContractBackend(ctx, store.intraBlockState, store.sr)) +func (store *ErigonWorkingSetStore) CreateGenesisStates(_ context.Context) error { + deployer := store.backend + for idx, contract := range systemContracts { + exists := deployer.Exists(contract.Address) + if !exists { + log.S().Infof("Deploying system contract [%d] %s", idx, contract.Address.String()) + msg := ðereum.CallMsg{ + From: common.BytesToAddress(systemContractCreatorAddr[:]), + Data: contract.Code, + Value: big.NewInt(0), + Gas: 10000000, + } + if addr, err := deployer.Deploy(msg); err != nil { + return fmt.Errorf("failed to deploy system contract %s: %w", contract.Address.String(), err) + } else if addr.String() != contract.Address.String() { + return fmt.Errorf("deployed contract address %s does not match expected address %s", addr.String(), contract.Address.String()) + } + log.S().Infof("System contract [%d] %s deployed successfully", idx, contract.Address.String()) + } else { + log.S().Infof("System contract [%d] %s already exists", idx, contract.Address.String()) + } + } + return nil } // Height returns the current height of the ErigonDB @@ -408,14 +405,14 @@ func (db *ErigonDB) Height() (uint64, error) { return height, nil } -func (store *ErigonWorkingSetStore) newContractBackend(ctx context.Context, intraBlockState *erigonstate.IntraBlockState, sr erigonstate.StateReader) *contractBackend { +func newContractBackend(ctx context.Context, intraBlockState *erigonstate.IntraBlockState, sr erigonstate.StateReader) *contractBackend { blkCtx := protocol.MustGetBlockCtx(ctx) g, ok := genesis.ExtractGenesisContext(ctx) if !ok { log.S().Panic("failed to extract genesis context from block context") } bcCtx := protocol.MustGetBlockchainCtx(ctx) - return NewContractBackend(store.intraBlockState, store.sr, blkCtx.BlockHeight, blkCtx.BlockTimeStamp, blkCtx.Producer, &g, bcCtx.EvmNetworkID) + return NewContractBackend(intraBlockState, sr, blkCtx.BlockHeight, blkCtx.BlockTimeStamp, blkCtx.Producer, &g, bcCtx.EvmNetworkID, protocol.MustGetFeatureCtx(ctx).UseZeroNonceForFreshAccount) } // KVStore returns nil as ErigonWorkingSetStore does not implement KVStore @@ -425,24 +422,31 @@ func (store *ErigonWorkingSetStore) KVStore() db.KVStore { // IntraBlockState returns the intraBlockState of the ErigonWorkingSetStore func (store *ErigonWorkingSetStore) IntraBlockState() *erigonstate.IntraBlockState { - return store.intraBlockState + return store.backend.intraBlockState } // StateReader returns the state reader of the ErigonWorkingSetStore func (store *ErigonWorkingSetStore) StateReader() erigonstate.StateReader { - return store.sr + return store.backend.org } -// ObjectContractStorage returns the ContractStorage interface for the given object -func ObjectContractStorage(obj any) ContractStorage { - if cs, ok := obj.(ContractStorage); ok { - return cs - } - if cs, ok := obj.(ContractStorageProxy); ok { - return cs.ContractStorageProxy() +func (store *ErigonWorkingSetStore) NewObjectStorage(ns string, obj any) (ObjectStorage, error) { + var contractAddr address.Address + switch ns { + case "Account": + return newAccountStorage( + common.BytesToAddress(systemContracts[AccountInfoContractIndex].Address.Bytes()), + store.backend, + ) + case "BlockMeta": + contractAddr = systemContracts[PollBlockMetaContractIndex].Address + default: + return nil, fmt.Errorf("unsupported namespace: %s", ns) } - if cs, ok := obj.(ContractStorageStandard); ok { - return NewContractStorageStandardWrapper(cs) + // TODO: cache storage + contract, err := systemcontracts.NewGenericStorageContract(common.BytesToAddress(contractAddr.Bytes()[:]), store.backend) + if err != nil { + return nil, err } - return nil + return newContractObjectStorage(contract), nil } diff --git a/state/factory/workingset.go b/state/factory/workingset.go index c59e780cb2..50be49e1f1 100644 --- a/state/factory/workingset.go +++ b/state/factory/workingset.go @@ -364,14 +364,11 @@ func (ws *workingSet) States(opts ...protocol.StateOption) (uint64, state.Iterat if cfg.Key != nil { return 0, nil, errors.Wrap(ErrNotSupported, "Read states with key option has not been implemented yet") } - keys, values, err := ws.store.States(cfg.Namespace, cfg.Keys, cfg.Object) - if err != nil { - return 0, nil, err - } - iter, err := state.NewIterator(keys, values) + iter, err := ws.store.States(cfg.Namespace, cfg.Object, cfg.Keys) if err != nil { return 0, nil, err } + return ws.height, iter, nil } @@ -1050,7 +1047,7 @@ func (ws *workingSet) Erigon() (*erigonstate.IntraBlockState, bool) { } return nil, false case *erigonWorkingSetStoreForSimulate: - return st.erigonStore.(*erigonstore.ErigonWorkingSetStore).IntraBlockState(), true + return st.erigonStore.IntraBlockState(), true default: return nil, false } diff --git a/state/factory/workingsetstore.go b/state/factory/workingsetstore.go index e1c460d936..cf5919fcf6 100644 --- a/state/factory/workingsetstore.go +++ b/state/factory/workingsetstore.go @@ -27,7 +27,7 @@ type ( PutObject(ns string, key []byte, object any) (err error) GetObject(ns string, key []byte, object any) error DeleteObject(ns string, key []byte, object any) error - States(ns string, keys [][]byte, object any) ([][]byte, [][]byte, error) + States(ns string, object any, keys [][]byte) (state.Iterator, error) Commit(context.Context, uint64) error Digest() hash.Hash256 Finalize(context.Context) error @@ -174,12 +174,19 @@ func (store *stateDBWorkingSetStore) getKV(ns string, key []byte) ([]byte, error return data, nil } -func (store *stateDBWorkingSetStore) States(ns string, keys [][]byte, obj any) ([][]byte, [][]byte, error) { +func (store *stateDBWorkingSetStore) States(ns string, obj any, keys [][]byte) (state.Iterator, error) { + var values [][]byte + var err error if store.readBuffer { // TODO: after the 180 HF, we can revert readBuffer, and always go this case - return readStates(store.flusher.KVStoreWithBuffer(), ns, keys) + keys, values, err = readStates(store.flusher.KVStoreWithBuffer(), ns, keys) + } else { + keys, values, err = readStates(store.flusher.BaseKVStore(), ns, keys) } - return readStates(store.flusher.BaseKVStore(), ns, keys) + if err != nil { + return nil, err + } + return state.NewIterator(keys, values) } func (store *stateDBWorkingSetStore) Finalize(ctx context.Context) error { diff --git a/state/factory/workingsetstore_erigon_simulate.go b/state/factory/workingsetstore_erigon_simulate.go index ff9c27c8d3..d31d604275 100644 --- a/state/factory/workingsetstore_erigon_simulate.go +++ b/state/factory/workingsetstore_erigon_simulate.go @@ -6,6 +6,7 @@ import ( "github.com/iotexproject/go-pkgs/hash" "github.com/iotexproject/iotex-core/v2/db" + "github.com/iotexproject/iotex-core/v2/state" "github.com/iotexproject/iotex-core/v2/state/factory/erigonstore" ) @@ -15,10 +16,10 @@ import ( type erigonWorkingSetStoreForSimulate struct { writer store workingSetStore // fallback to statedb for staking, rewarding and poll - erigonStore workingSetStore + erigonStore *erigonstore.ErigonWorkingSetStore } -func newErigonWorkingSetStoreForSimulate(store workingSetStore, erigonStore workingSetStore) *erigonWorkingSetStoreForSimulate { +func newErigonWorkingSetStoreForSimulate(store workingSetStore, erigonStore *erigonstore.ErigonWorkingSetStore) *erigonWorkingSetStoreForSimulate { return &erigonWorkingSetStoreForSimulate{ store: store, erigonStore: erigonStore, @@ -35,20 +36,26 @@ func (store *erigonWorkingSetStoreForSimulate) Stop(context.Context) error { } func (store *erigonWorkingSetStoreForSimulate) GetObject(ns string, key []byte, obj any) error { - storage := erigonstore.ObjectContractStorage(obj) + storage, err := store.erigonStore.NewObjectStorage(ns, obj) + if err != nil { + return err + } if storage != nil { return store.erigonStore.GetObject(ns, key, obj) } return store.store.GetObject(ns, key, obj) } -func (store *erigonWorkingSetStoreForSimulate) States(ns string, keys [][]byte, obj any) ([][]byte, [][]byte, error) { - storage := erigonstore.ObjectContractStorage(obj) +func (store *erigonWorkingSetStoreForSimulate) States(ns string, obj any, keys [][]byte) (state.Iterator, error) { + storage, err := store.erigonStore.NewObjectStorage(ns, obj) + if err != nil { + return nil, err + } if storage != nil { - return store.erigonStore.States(ns, keys, obj) + return store.erigonStore.States(ns, obj, keys) } // currently only used for staking & poll, no need to read from erigon - return store.store.States(ns, keys, obj) + return store.store.States(ns, obj, keys) } func (store *erigonWorkingSetStoreForSimulate) Finalize(_ context.Context) error { diff --git a/state/factory/workingsetstore_test.go b/state/factory/workingsetstore_test.go index a4504223e5..de104e6e5b 100644 --- a/state/factory/workingsetstore_test.go +++ b/state/factory/workingsetstore_test.go @@ -11,12 +11,14 @@ import ( "encoding/hex" "testing" + "github.com/pkg/errors" "github.com/stretchr/testify/require" "github.com/iotexproject/iotex-core/v2/action/protocol" "github.com/iotexproject/iotex-core/v2/db" "github.com/iotexproject/iotex-core/v2/db/batch" "github.com/iotexproject/iotex-core/v2/pkg/util/byteutil" + "github.com/iotexproject/iotex-core/v2/state" ) type valueBytes []byte @@ -66,8 +68,18 @@ func TestStateDBWorkingSetStore(t *testing.T) { err = store.GetObject(namespace, key3, &valueInStore) require.NoError(err) require.True(bytes.Equal(value3, valueInStore)) - _, valuesInStore, err := store.States(namespace, [][]byte{key1, key2, key3}, nil) - require.Equal(3, len(valuesInStore)) + iter, err := store.States(namespace, nil, [][]byte{key1, key2, key3}) + require.NoError(err) + require.Equal(3, iter.Size()) + var valuesInStore []valueBytes + for { + vb := valueBytes{} + if _, err := iter.Next(&vb); err == nil { + valuesInStore = append(valuesInStore, vb) + } else { + break + } + } require.True(bytes.Equal(value1, valuesInStore[0])) require.True(bytes.Equal(value2, valuesInStore[1])) require.True(bytes.Equal(value3, valuesInStore[2])) @@ -79,8 +91,22 @@ func TestStateDBWorkingSetStore(t *testing.T) { require.NoError(store.DeleteObject(namespace, key1, &valueInStore)) err = store.GetObject(namespace, key1, &valueInStore) require.Error(err) - _, valuesInStore, err = store.States(namespace, [][]byte{key1, key2, key3}, &valueInStore) - require.Equal(3, len(valuesInStore)) + iter, err = store.States(namespace, &valueInStore, [][]byte{key1, key2, key3}) + require.NoError(err) + require.Equal(3, iter.Size()) + valuesInStore = []valueBytes{} + for { + vb := valueBytes{} + switch _, err := iter.Next(&vb); errors.Cause(err) { + case state.ErrNilValue: + valuesInStore = append(valuesInStore, nil) + continue + case nil: + valuesInStore = append(valuesInStore, vb) + continue + } + break + } require.Nil(valuesInStore[0]) require.True(bytes.Equal(value2, valuesInStore[1])) require.True(bytes.Equal(value3, valuesInStore[2])) diff --git a/state/factory/workingsetstore_with_secondary.go b/state/factory/workingsetstore_with_secondary.go index d053271d0d..7ca49dc934 100644 --- a/state/factory/workingsetstore_with_secondary.go +++ b/state/factory/workingsetstore_with_secondary.go @@ -9,6 +9,7 @@ import ( "github.com/iotexproject/iotex-core/v2/db" "github.com/iotexproject/iotex-core/v2/pkg/log" + "github.com/iotexproject/iotex-core/v2/state" ) var ( @@ -24,7 +25,7 @@ var ( type reader interface { // Get(string, []byte) ([]byte, error) GetObject(string, []byte, any) error - States(string, [][]byte, any) ([][]byte, [][]byte, error) + States(string, any, [][]byte) (state.Iterator, error) Digest() hash.Hash256 // Filter(string, db.Condition, []byte, []byte) ([][]byte, [][]byte, error) } @@ -151,8 +152,8 @@ func (store *workingSetStoreWithSecondary) GetObject(ns string, key []byte, obj return store.reader.GetObject(ns, key, obj) } -func (store *workingSetStoreWithSecondary) States(ns string, keys [][]byte, obj any) ([][]byte, [][]byte, error) { - return store.reader.States(ns, keys, obj) +func (store *workingSetStoreWithSecondary) States(ns string, obj any, keys [][]byte) (state.Iterator, error) { + return store.reader.States(ns, obj, keys) } func (store *workingSetStoreWithSecondary) KVStore() db.KVStore { diff --git a/state/state.go b/state/state.go index 6dce1021f8..0751fedb68 100644 --- a/state/state.go +++ b/state/state.go @@ -6,10 +6,7 @@ package state import ( - "github.com/iotexproject/iotex-address/address" "github.com/pkg/errors" - - "github.com/iotexproject/iotex-core/v2/systemcontracts" ) var ( @@ -54,9 +51,3 @@ func Deserialize(x interface{}, data []byte) error { } panic("data holder doesn't implement Deserializer interface!") } - -type ContractBackend interface { - systemcontracts.ContractBackend - PutAccount(addr address.Address, acc *Account) error - Account(addr address.Address) (*Account, error) -} diff --git a/systemcontracts/generic_storage.go b/systemcontracts/generic_storage.go index 33d69d1e61..4b070482ce 100644 --- a/systemcontracts/generic_storage.go +++ b/systemcontracts/generic_storage.go @@ -14,36 +14,10 @@ import ( "github.com/iotexproject/iotex-core/v2/pkg/log" ) -// GenericValue represents the value structure in the GenericStorage contract -type GenericValue struct { - PrimaryData []byte `json:"primaryData"` - SecondaryData []byte `json:"secondaryData"` - AuxiliaryData []byte `json:"auxiliaryData"` -} - -// BatchGetResult represents the result of a batch get operation -type BatchGetResult struct { - Values []GenericValue `json:"values"` - ExistsFlags []bool `json:"existsFlags"` -} - -// ListResult represents the result of a list operation -type ListResult struct { - KeyList [][]byte `json:"keyList"` - Values []GenericValue `json:"values"` - Total *big.Int `json:"total"` -} - -// ListKeysResult represents the result of a listKeys operation -type ListKeysResult struct { - KeyList [][]byte `json:"keyList"` - Total *big.Int `json:"total"` -} - -// GetResult represents the result of a get operation -type GetResult struct { - Value GenericValue `json:"value"` - KeyExists bool `json:"keyExists"` +// ContractBackend defines the interface for contract backend operations +type ContractBackend interface { + Call(callMsg *ethereum.CallMsg) ([]byte, error) + Handle(callMsg *ethereum.CallMsg) error } // GenericStorageContract provides an interface to interact with the GenericStorage smart contract @@ -86,7 +60,7 @@ func (g *GenericStorageContract) Put(key []byte, value GenericValue) error { // Execute the transaction callMsg := ðereum.CallMsg{ - From: common.BytesToAddress(systemContractCreatorAddr[:]), + From: common.Address{}, To: &g.contractAddress, Data: data, Value: big.NewInt(0), @@ -131,7 +105,7 @@ func (g *GenericStorageContract) Get(key []byte) (*GetResult, error) { // Execute the call callMsg := ðereum.CallMsg{ - From: common.BytesToAddress(systemContractCreatorAddr[:]), + From: common.Address{}, To: &g.contractAddress, Data: data, Value: big.NewInt(0), @@ -179,7 +153,7 @@ func (g *GenericStorageContract) Remove(key []byte) error { // Execute the transaction callMsg := ðereum.CallMsg{ - From: common.BytesToAddress(systemContractCreatorAddr[:]), + From: common.Address{}, To: &g.contractAddress, Data: data, Value: big.NewInt(0), @@ -214,7 +188,7 @@ func (g *GenericStorageContract) BatchGet(keys [][]byte) (*BatchGetResult, error // Execute the call callMsg := ðereum.CallMsg{ - From: common.BytesToAddress(systemContractCreatorAddr[:]), + From: common.Address{}, To: &g.contractAddress, Data: data, Value: big.NewInt(0), @@ -257,7 +231,7 @@ func (g *GenericStorageContract) List(offset, limit uint64) (*ListResult, error) // Execute the call callMsg := ðereum.CallMsg{ - From: common.BytesToAddress(systemContractCreatorAddr[:]), + From: common.Address{}, To: &g.contractAddress, Data: data, Value: big.NewInt(0), @@ -304,7 +278,7 @@ func (g *GenericStorageContract) ListKeys(offset, limit uint64) (*ListKeysResult // Execute the call callMsg := ðereum.CallMsg{ - From: common.BytesToAddress(systemContractCreatorAddr[:]), + From: common.Address{}, To: &g.contractAddress, Data: data, Value: big.NewInt(0), @@ -354,7 +328,7 @@ func (g *GenericStorageContract) Exists(key []byte) (bool, error) { // Execute the call callMsg := ðereum.CallMsg{ - From: common.BytesToAddress(systemContractCreatorAddr[:]), + From: common.Address{}, To: &g.contractAddress, Data: data, Value: big.NewInt(0), @@ -393,7 +367,7 @@ func (g *GenericStorageContract) Count() (*big.Int, error) { // Execute the call callMsg := ðereum.CallMsg{ - From: common.BytesToAddress(systemContractCreatorAddr[:]), + From: common.Address{}, To: &g.contractAddress, Data: data, Value: big.NewInt(0), @@ -431,7 +405,7 @@ func (g *GenericStorageContract) Clear() error { // Execute the transaction callMsg := ðereum.CallMsg{ - From: common.BytesToAddress(systemContractCreatorAddr[:]), + From: common.Address{}, To: &g.contractAddress, Data: data, Value: big.NewInt(0), diff --git a/systemcontracts/namespace_storage.go b/systemcontracts/namespace_storage.go index 72320b8058..7b607d9102 100644 --- a/systemcontracts/namespace_storage.go +++ b/systemcontracts/namespace_storage.go @@ -81,7 +81,7 @@ func (ns *NamespaceStorageContract) Put(namespace string, key []byte, value Name // Execute the transaction callMsg := ðereum.CallMsg{ - From: common.BytesToAddress(systemContractCreatorAddr[:]), + From: common.Address{}, To: &ns.contractAddress, Data: data, Value: big.NewInt(0), @@ -117,7 +117,7 @@ func (ns *NamespaceStorageContract) Get(namespace string, key []byte) (*Namespac // Execute the call callMsg := ðereum.CallMsg{ - From: common.BytesToAddress(systemContractCreatorAddr[:]), + From: common.Address{}, To: &ns.contractAddress, Data: data, Value: big.NewInt(0), @@ -169,7 +169,7 @@ func (ns *NamespaceStorageContract) Remove(namespace string, key []byte) error { // Execute the transaction callMsg := ðereum.CallMsg{ - From: common.BytesToAddress(systemContractCreatorAddr[:]), + From: common.Address{}, To: &ns.contractAddress, Data: data, Value: big.NewInt(0), @@ -205,7 +205,7 @@ func (ns *NamespaceStorageContract) Exists(namespace string, key []byte) (bool, // Execute the call callMsg := ðereum.CallMsg{ - From: common.BytesToAddress(systemContractCreatorAddr[:]), + From: common.Address{}, To: &ns.contractAddress, Data: data, Value: big.NewInt(0), @@ -248,7 +248,7 @@ func (ns *NamespaceStorageContract) BatchGet(namespace string, keys [][]byte) (* // Execute the call callMsg := ðereum.CallMsg{ - From: common.BytesToAddress(systemContractCreatorAddr[:]), + From: common.Address{}, To: &ns.contractAddress, Data: data, Value: big.NewInt(0), @@ -302,7 +302,7 @@ func (ns *NamespaceStorageContract) BatchPut(namespace string, keys [][]byte, va // Execute the transaction callMsg := ðereum.CallMsg{ - From: common.BytesToAddress(systemContractCreatorAddr[:]), + From: common.Address{}, To: &ns.contractAddress, Data: data, Value: big.NewInt(0), @@ -341,7 +341,7 @@ func (ns *NamespaceStorageContract) List(namespace string, offset, limit *big.In // Execute the call callMsg := ðereum.CallMsg{ - From: common.BytesToAddress(systemContractCreatorAddr[:]), + From: common.Address{}, To: &ns.contractAddress, Data: data, Value: big.NewInt(0), @@ -397,7 +397,7 @@ func (ns *NamespaceStorageContract) ListKeys(namespace string, offset, limit *bi // Execute the call callMsg := ðereum.CallMsg{ - From: common.BytesToAddress(systemContractCreatorAddr[:]), + From: common.Address{}, To: &ns.contractAddress, Data: data, Value: big.NewInt(0), @@ -447,7 +447,7 @@ func (ns *NamespaceStorageContract) ListNamespaces(offset, limit *big.Int) (*Nam // Execute the call callMsg := ðereum.CallMsg{ - From: common.BytesToAddress(systemContractCreatorAddr[:]), + From: common.Address{}, To: &ns.contractAddress, Data: data, Value: big.NewInt(0), @@ -496,7 +496,7 @@ func (ns *NamespaceStorageContract) HasNamespace(namespace string) (bool, error) // Execute the call callMsg := ðereum.CallMsg{ - From: common.BytesToAddress(systemContractCreatorAddr[:]), + From: common.Address{}, To: &ns.contractAddress, Data: data, Value: big.NewInt(0), @@ -533,7 +533,7 @@ func (ns *NamespaceStorageContract) CountInNamespace(namespace string) (*big.Int // Execute the call callMsg := ðereum.CallMsg{ - From: common.BytesToAddress(systemContractCreatorAddr[:]), + From: common.Address{}, To: &ns.contractAddress, Data: data, Value: big.NewInt(0), @@ -565,7 +565,7 @@ func (ns *NamespaceStorageContract) NamespaceCount() (*big.Int, error) { // Execute the call callMsg := ðereum.CallMsg{ - From: common.BytesToAddress(systemContractCreatorAddr[:]), + From: common.Address{}, To: &ns.contractAddress, Data: data, Value: big.NewInt(0), @@ -597,7 +597,7 @@ func (ns *NamespaceStorageContract) TotalCount() (*big.Int, error) { // Execute the call callMsg := ðereum.CallMsg{ - From: common.BytesToAddress(systemContractCreatorAddr[:]), + From: common.Address{}, To: &ns.contractAddress, Data: data, Value: big.NewInt(0), @@ -634,7 +634,7 @@ func (ns *NamespaceStorageContract) ClearNamespace(namespace string) error { // Execute the transaction callMsg := ðereum.CallMsg{ - From: common.BytesToAddress(systemContractCreatorAddr[:]), + From: common.Address{}, To: &ns.contractAddress, Data: data, Value: big.NewInt(0), @@ -661,7 +661,7 @@ func (ns *NamespaceStorageContract) ClearAll() error { // Execute the transaction callMsg := ðereum.CallMsg{ - From: common.BytesToAddress(systemContractCreatorAddr[:]), + From: common.Address{}, To: &ns.contractAddress, Data: data, Value: big.NewInt(0), diff --git a/systemcontracts/namespace_storage_wrapper.go b/systemcontracts/namespace_storage_wrapper.go new file mode 100644 index 0000000000..5cd0d79c53 --- /dev/null +++ b/systemcontracts/namespace_storage_wrapper.go @@ -0,0 +1,85 @@ +package systemcontracts + +import ( + "math/big" + + "github.com/ethereum/go-ethereum/common" + "github.com/pkg/errors" +) + +// NamespaceStorageContractWrapper wraps the NamespaceStorageContract +type NamespaceStorageContractWrapper struct { + contract NamespaceStorageContract + ns string +} + +func NewNamespaceStorageContractWrapper(contractAddress common.Address, backend ContractBackend, ns string) (*NamespaceStorageContractWrapper, error) { + if ns == "" { + return nil, errors.New("namespace cannot be empty") + } + + contract, err := NewNamespaceStorageContract(contractAddress, backend) + if err != nil { + return nil, errors.Wrap(err, "failed to create NamespaceStorage contract") + } + + return &NamespaceStorageContractWrapper{ + contract: *contract, + ns: ns, + }, nil +} + +// Address returns the contract address +func (ns *NamespaceStorageContractWrapper) Address() common.Address { + return ns.contract.Address() +} + +// Put stores data with the given namespace and key +func (ns *NamespaceStorageContractWrapper) Put(key []byte, value NamespaceGenericValue) error { + return ns.contract.Put(ns.ns, key, value) +} + +// Get retrieves data by namespace and key +func (ns *NamespaceStorageContractWrapper) Get(key []byte) (*NamespaceGetResult, error) { + return ns.contract.Get(ns.ns, key) +} + +// Remove deletes data by namespace and key +func (ns *NamespaceStorageContractWrapper) Remove(key []byte) error { + return ns.contract.Remove(ns.ns, key) +} + +// Exists checks if a key exists in a namespace +func (ns *NamespaceStorageContractWrapper) Exists(key []byte) (bool, error) { + return ns.contract.Exists(ns.ns, key) +} + +// BatchGet retrieves multiple values by their keys within a namespace +func (ns *NamespaceStorageContractWrapper) BatchGet(keys [][]byte) (*NamespaceBatchGetResult, error) { + return ns.contract.BatchGet(ns.ns, keys) +} + +// BatchPut stores multiple key-value pairs in the same namespace +func (ns *NamespaceStorageContractWrapper) BatchPut(keys [][]byte, values []NamespaceGenericValue) error { + return ns.contract.BatchPut(ns.ns, keys, values) +} + +// List retrieves all stored data in a namespace with pagination +func (ns *NamespaceStorageContractWrapper) List(offset, limit *big.Int) (*NamespaceListResult, error) { + return ns.contract.List(ns.ns, offset, limit) +} + +// ListKeys retrieves all keys in a namespace with pagination +func (ns *NamespaceStorageContractWrapper) ListKeys(offset, limit *big.Int) (*NamespaceListKeysResult, error) { + return ns.contract.ListKeys(ns.ns, offset, limit) +} + +// Count returns the number of items in the namespace +func (ns *NamespaceStorageContractWrapper) Count() (*big.Int, error) { + return ns.contract.CountInNamespace(ns.ns) +} + +// Clear removes all data in the namespace +func (ns *NamespaceStorageContractWrapper) Clear() error { + return ns.contract.ClearNamespace(ns.ns) +} diff --git a/systemcontracts/storage.go b/systemcontracts/storage.go new file mode 100644 index 0000000000..278ab80b53 --- /dev/null +++ b/systemcontracts/storage.go @@ -0,0 +1,114 @@ +package systemcontracts + +import ( + "math/big" + + "github.com/ethereum/go-ethereum/common" + "github.com/iotexproject/iotex-core/v2/state" + "github.com/pkg/errors" +) + +type ( + + // GenericValue represents the value structure in the GenericStorage contract + GenericValue struct { + PrimaryData []byte `json:"primaryData"` + SecondaryData []byte `json:"secondaryData"` + AuxiliaryData []byte `json:"auxiliaryData"` + } + + // GenericValueContainer is an interface for objects that can be encoded/decoded to/from GenericValue + GenericValueContainer interface { + Decode(data GenericValue) error + Encode() (GenericValue, error) + } + + // GenericValueObjectIterator is an iterator for GenericValue objects + GenericValueObjectIterator struct { + keys [][]byte + values []GenericValue + exists []bool + cur int + } + + // BatchGetResult represents the result of a batch get operation + BatchGetResult struct { + Values []GenericValue `json:"values"` + ExistsFlags []bool `json:"existsFlags"` + } + + // ListResult represents the result of a list operation + ListResult struct { + KeyList [][]byte `json:"keyList"` + Values []GenericValue `json:"values"` + Total *big.Int `json:"total"` + } + + // ListKeysResult represents the result of a listKeys operation + ListKeysResult struct { + KeyList [][]byte `json:"keyList"` + Total *big.Int `json:"total"` + } + + // GetResult represents the result of a get operation + GetResult struct { + Value GenericValue `json:"value"` + KeyExists bool `json:"keyExists"` + } + // StorageContract provides an interface to interact with the storage smart contract + StorageContract interface { + Address() common.Address + Put(key []byte, value GenericValue) error + Get(key []byte) (*GetResult, error) + Remove(key []byte) error + Exists(key []byte) (bool, error) + List(uint64, uint64) (*ListResult, error) + ListKeys(uint64, uint64) (*ListKeysResult, error) + BatchGet(keys [][]byte) (*BatchGetResult, error) + Count() (*big.Int, error) + } +) + +// DecodeGenericValue decodes a GenericValue into a specific object +func DecodeGenericValue(o interface{}, data GenericValue) error { + if o == nil { + return errors.New("nil object") + } + if oo, ok := o.(GenericValueContainer); ok { + return oo.Decode(data) + } + return errors.New("unsupported object type") +} + +// NewGenericValueObjectIterator creates a new GenericValueObjectIterator +func NewGenericValueObjectIterator(keys [][]byte, values []GenericValue, exists []bool) (state.Iterator, error) { + return &GenericValueObjectIterator{ + keys: keys, + values: values, + exists: exists, + cur: 0, + }, nil +} + +// Size returns the size of the iterator +func (gvoi *GenericValueObjectIterator) Size() int { + return len(gvoi.values) +} + +// Next returns the next key-value pair from the iterator +func (gvoi *GenericValueObjectIterator) Next(o interface{}) ([]byte, error) { + if gvoi.cur >= len(gvoi.values) { + return nil, state.ErrOutOfBoundary + } + value := gvoi.values[gvoi.cur] + key := gvoi.keys[gvoi.cur] + gvoi.cur++ + if gvoi.exists != nil && !gvoi.exists[gvoi.cur] { + gvoi.cur++ + return key, state.ErrNilValue + } + if err := DecodeGenericValue(o, value); err != nil { + return nil, err + } + return key, nil +} From 377736420c390fa53fcd2da068aadb51b1550474 Mon Sep 17 00:00:00 2001 From: zhi Date: Wed, 17 Sep 2025 20:12:24 +0800 Subject: [PATCH 20/26] fix owner issue --- api/coreservice.go | 1 + state/factory/erigonstore/accountstorage.go | 1 + .../factory/erigonstore/workingsetstore_erigon.go | 7 ++++++- systemcontracts/generic_storage.go | 9 ++++++--- systemcontracts/namespace_storage.go | 14 ++++++++------ systemcontracts/namespace_storage_wrapper.go | 4 ++-- 6 files changed, 24 insertions(+), 12 deletions(-) diff --git a/api/coreservice.go b/api/coreservice.go index e4a1f0fe02..8694d658c3 100644 --- a/api/coreservice.go +++ b/api/coreservice.go @@ -371,6 +371,7 @@ func (core *coreService) BalanceAt(ctx context.Context, addr address.Address, he BlockHeight: bcCtx.Tip.Height, BlockTimeStamp: bcCtx.Tip.Timestamp, }) + ctx = protocol.WithFeatureCtx(ctx) if addrStr == address.RewardingPoolAddr || addrStr == address.StakingBucketPoolAddr || addrStr == address.RewardingProtocol || addrStr == address.StakingProtocolAddr { acc, _, err := core.getProtocolAccount(ctx, addrStr) diff --git a/state/factory/erigonstore/accountstorage.go b/state/factory/erigonstore/accountstorage.go index a587b30559..5749a6cbe7 100644 --- a/state/factory/erigonstore/accountstorage.go +++ b/state/factory/erigonstore/accountstorage.go @@ -22,6 +22,7 @@ func newAccountStorage(addr common.Address, backend *contractBackend) (*accountS contract, err := systemcontracts.NewGenericStorageContract( addr, backend, + common.Address(systemContractCreatorAddr), ) if err != nil { return nil, errors.Wrap(err, "failed to create account storage contract") diff --git a/state/factory/erigonstore/workingsetstore_erigon.go b/state/factory/erigonstore/workingsetstore_erigon.go index 46cc5a828e..4a5582a320 100644 --- a/state/factory/erigonstore/workingsetstore_erigon.go +++ b/state/factory/erigonstore/workingsetstore_erigon.go @@ -434,17 +434,22 @@ func (store *ErigonWorkingSetStore) NewObjectStorage(ns string, obj any) (Object var contractAddr address.Address switch ns { case "Account": + if _, ok := obj.(*state.Account); !ok { + return nil, nil + } return newAccountStorage( common.BytesToAddress(systemContracts[AccountInfoContractIndex].Address.Bytes()), store.backend, ) case "BlockMeta": contractAddr = systemContracts[PollBlockMetaContractIndex].Address + case "Staking", "Rewarding": + return nil, nil default: return nil, fmt.Errorf("unsupported namespace: %s", ns) } // TODO: cache storage - contract, err := systemcontracts.NewGenericStorageContract(common.BytesToAddress(contractAddr.Bytes()[:]), store.backend) + contract, err := systemcontracts.NewGenericStorageContract(common.BytesToAddress(contractAddr.Bytes()[:]), store.backend, common.Address(systemContractCreatorAddr)) if err != nil { return nil, err } diff --git a/systemcontracts/generic_storage.go b/systemcontracts/generic_storage.go index 4b070482ce..24d0413e14 100644 --- a/systemcontracts/generic_storage.go +++ b/systemcontracts/generic_storage.go @@ -25,10 +25,11 @@ type GenericStorageContract struct { contractAddress common.Address backend ContractBackend abi abi.ABI + owner common.Address } // NewGenericStorageContract creates a new GenericStorage contract instance -func NewGenericStorageContract(contractAddress common.Address, backend ContractBackend) (*GenericStorageContract, error) { +func NewGenericStorageContract(contractAddress common.Address, backend ContractBackend, owner common.Address) (*GenericStorageContract, error) { abi, err := abi.JSON(strings.NewReader(GenericStorageABI)) if err != nil { return nil, errors.Wrap(err, "failed to parse GenericStorage ABI") @@ -38,9 +39,11 @@ func NewGenericStorageContract(contractAddress common.Address, backend ContractB contractAddress: contractAddress, backend: backend, abi: abi, + owner: owner, }, nil } +// Address returns the contract address func (g *GenericStorageContract) Address() common.Address { return g.contractAddress } @@ -60,7 +63,7 @@ func (g *GenericStorageContract) Put(key []byte, value GenericValue) error { // Execute the transaction callMsg := ðereum.CallMsg{ - From: common.Address{}, + From: g.owner, To: &g.contractAddress, Data: data, Value: big.NewInt(0), @@ -153,7 +156,7 @@ func (g *GenericStorageContract) Remove(key []byte) error { // Execute the transaction callMsg := ðereum.CallMsg{ - From: common.Address{}, + From: g.owner, To: &g.contractAddress, Data: data, Value: big.NewInt(0), diff --git a/systemcontracts/namespace_storage.go b/systemcontracts/namespace_storage.go index 7b607d9102..654a57979b 100644 --- a/systemcontracts/namespace_storage.go +++ b/systemcontracts/namespace_storage.go @@ -42,10 +42,11 @@ type NamespaceStorageContract struct { contractAddress common.Address backend ContractBackend abi abi.ABI + owner common.Address } // NewNamespaceStorageContract creates a new NamespaceStorage contract instance -func NewNamespaceStorageContract(contractAddress common.Address, backend ContractBackend) (*NamespaceStorageContract, error) { +func NewNamespaceStorageContract(contractAddress common.Address, backend ContractBackend, owner common.Address) (*NamespaceStorageContract, error) { abi, err := abi.JSON(strings.NewReader(NamespaceStorageABI)) if err != nil { return nil, errors.Wrap(err, "failed to parse NamespaceStorage ABI") @@ -55,6 +56,7 @@ func NewNamespaceStorageContract(contractAddress common.Address, backend Contrac contractAddress: contractAddress, backend: backend, abi: abi, + owner: owner, }, nil } @@ -81,7 +83,7 @@ func (ns *NamespaceStorageContract) Put(namespace string, key []byte, value Name // Execute the transaction callMsg := ðereum.CallMsg{ - From: common.Address{}, + From: ns.owner, To: &ns.contractAddress, Data: data, Value: big.NewInt(0), @@ -169,7 +171,7 @@ func (ns *NamespaceStorageContract) Remove(namespace string, key []byte) error { // Execute the transaction callMsg := ðereum.CallMsg{ - From: common.Address{}, + From: ns.owner, To: &ns.contractAddress, Data: data, Value: big.NewInt(0), @@ -302,7 +304,7 @@ func (ns *NamespaceStorageContract) BatchPut(namespace string, keys [][]byte, va // Execute the transaction callMsg := ðereum.CallMsg{ - From: common.Address{}, + From: ns.owner, To: &ns.contractAddress, Data: data, Value: big.NewInt(0), @@ -634,7 +636,7 @@ func (ns *NamespaceStorageContract) ClearNamespace(namespace string) error { // Execute the transaction callMsg := ðereum.CallMsg{ - From: common.Address{}, + From: ns.owner, To: &ns.contractAddress, Data: data, Value: big.NewInt(0), @@ -661,7 +663,7 @@ func (ns *NamespaceStorageContract) ClearAll() error { // Execute the transaction callMsg := ðereum.CallMsg{ - From: common.Address{}, + From: ns.owner, To: &ns.contractAddress, Data: data, Value: big.NewInt(0), diff --git a/systemcontracts/namespace_storage_wrapper.go b/systemcontracts/namespace_storage_wrapper.go index 5cd0d79c53..2b957cfd27 100644 --- a/systemcontracts/namespace_storage_wrapper.go +++ b/systemcontracts/namespace_storage_wrapper.go @@ -13,12 +13,12 @@ type NamespaceStorageContractWrapper struct { ns string } -func NewNamespaceStorageContractWrapper(contractAddress common.Address, backend ContractBackend, ns string) (*NamespaceStorageContractWrapper, error) { +func NewNamespaceStorageContractWrapper(contractAddress common.Address, backend ContractBackend, owner common.Address, ns string) (*NamespaceStorageContractWrapper, error) { if ns == "" { return nil, errors.New("namespace cannot be empty") } - contract, err := NewNamespaceStorageContract(contractAddress, backend) + contract, err := NewNamespaceStorageContract(contractAddress, backend, owner) if err != nil { return nil, errors.Wrap(err, "failed to create NamespaceStorage contract") } From 6a3082ee4c128790e7e47268e32f7924f11e5014 Mon Sep 17 00:00:00 2001 From: zhi Date: Thu, 18 Sep 2025 11:14:55 +0800 Subject: [PATCH 21/26] fix unit test --- api/coreservice.go | 1 + state/factory/erigonstore/accountstorage.go | 3 +-- state/factory/erigonstore/workingsetstore_erigon.go | 5 ++--- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/api/coreservice.go b/api/coreservice.go index 8694d658c3..5ec42406a5 100644 --- a/api/coreservice.go +++ b/api/coreservice.go @@ -2256,6 +2256,7 @@ func (core *coreService) workingSetAt(ctx context.Context, height uint64) (conte BlockHeight: bcCtx.Tip.Height, BlockTimeStamp: bcCtx.Tip.Timestamp, }) + ctx = protocol.WithFeatureCtx(ctx) ws, err := core.sf.WorkingSetAtHeight(ctx, height) if err != nil { return ctx, nil, status.Error(codes.Internal, err.Error()) diff --git a/state/factory/erigonstore/accountstorage.go b/state/factory/erigonstore/accountstorage.go index 5749a6cbe7..68eecc1181 100644 --- a/state/factory/erigonstore/accountstorage.go +++ b/state/factory/erigonstore/accountstorage.go @@ -4,9 +4,9 @@ import ( erigonComm "github.com/erigontech/erigon-lib/common" "github.com/erigontech/erigon/core/types/accounts" "github.com/ethereum/go-ethereum/common" - "github.com/gogo/protobuf/proto" "github.com/holiman/uint256" "github.com/pkg/errors" + "google.golang.org/protobuf/proto" "github.com/iotexproject/iotex-core/v2/action/protocol/account/accountpb" "github.com/iotexproject/iotex-core/v2/state" @@ -120,7 +120,6 @@ func (as *accountStorage) Store(key []byte, value any) error { pbAcc := acc.ToProto() pbAcc.Balance = "" pbAcc.Nonce = 0 - pbAcc.CodeHash = nil data, err := proto.Marshal(pbAcc) if err != nil { return errors.Wrapf(err, "failed to marshal account %x", addr.Bytes()) diff --git a/state/factory/erigonstore/workingsetstore_erigon.go b/state/factory/erigonstore/workingsetstore_erigon.go index 4a5582a320..bbe17b068e 100644 --- a/state/factory/erigonstore/workingsetstore_erigon.go +++ b/state/factory/erigonstore/workingsetstore_erigon.go @@ -443,10 +443,9 @@ func (store *ErigonWorkingSetStore) NewObjectStorage(ns string, obj any) (Object ) case "BlockMeta": contractAddr = systemContracts[PollBlockMetaContractIndex].Address - case "Staking", "Rewarding": - return nil, nil default: - return nil, fmt.Errorf("unsupported namespace: %s", ns) + // TODO: fail unknown namespace + return nil, nil } // TODO: cache storage contract, err := systemcontracts.NewGenericStorageContract(common.BytesToAddress(contractAddr.Bytes()[:]), store.backend, common.Address(systemContractCreatorAddr)) From edb5f0955805a2d32ede64b87bd4920cb61cf81a Mon Sep 17 00:00:00 2001 From: envestcc Date: Thu, 25 Sep 2025 16:05:45 +0800 Subject: [PATCH 22/26] address comment --- state/factory/erigonstore/contract_backend.go | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/state/factory/erigonstore/contract_backend.go b/state/factory/erigonstore/contract_backend.go index e33beebae9..093fd95584 100644 --- a/state/factory/erigonstore/contract_backend.go +++ b/state/factory/erigonstore/contract_backend.go @@ -157,8 +157,10 @@ func (backend *contractBackend) prepare(intra evmtypes.IntraBlockState) (*vm.EVM ctx = genesis.WithGenesisContext(ctx, *backend.g) ctx = protocol.WithBlockchainCtx(ctx, protocol.BlockchainCtx{ GetBlockTime: func(u uint64) (time.Time, error) { - interval := 2500 * time.Millisecond - return backend.timestamp.Add(interval * time.Duration(u-backend.height)), nil + if u == backend.height { + return backend.timestamp, nil + } + return time.Time{}, errors.New("only current block is supported") }, EvmNetworkID: backend.evmNetworkID, }) From c0a60847e15d246387e72c699f5fb7fa37b03ea3 Mon Sep 17 00:00:00 2001 From: envestcc Date: Thu, 25 Sep 2025 17:54:05 +0800 Subject: [PATCH 23/26] object registry --- state/factory/erigonstore/registry.go | 168 ++++++++++++++++++ state/factory/erigonstore/systemcontracts.go | 7 +- .../erigonstore/workingsetstore_erigon.go | 26 +-- 3 files changed, 180 insertions(+), 21 deletions(-) create mode 100644 state/factory/erigonstore/registry.go diff --git a/state/factory/erigonstore/registry.go b/state/factory/erigonstore/registry.go new file mode 100644 index 0000000000..7ad83ef4f2 --- /dev/null +++ b/state/factory/erigonstore/registry.go @@ -0,0 +1,168 @@ +package erigonstore + +import ( + "reflect" + + "github.com/ethereum/go-ethereum/common" + "github.com/pkg/errors" + "go.uber.org/zap" + + "github.com/iotexproject/iotex-core/v2/pkg/log" + "github.com/iotexproject/iotex-core/v2/state" + "github.com/iotexproject/iotex-core/v2/systemcontracts" +) + +var ( + // ErrObjectStorageNotRegistered is returned when an object storage is not registered + ErrObjectStorageNotRegistered = errors.New("object storage not registered") + // ErrObjectStorageAlreadyRegistered is returned when an object storage is already registered + ErrObjectStorageAlreadyRegistered = errors.New("object storage already registered") +) + +var ( + storageRegistry = newObjectStorageRegistry() +) + +// ObjectStorageRegistry is a registry for object storage +type ObjectStorageRegistry struct { + contracts map[string]map[reflect.Type]int +} + +func init() { + if err := storageRegistry.RegisterAccount(state.AccountKVNamespace, &state.Account{}); err != nil { + log.L().Panic("failed to register account storage", zap.Error(err)) + } +} + +// GetObjectStorageRegistry returns the global object storage registry +func GetObjectStorageRegistry() *ObjectStorageRegistry { + return storageRegistry +} + +func newObjectStorageRegistry() *ObjectStorageRegistry { + return &ObjectStorageRegistry{ + contracts: make(map[string]map[reflect.Type]int), + } +} + +// ObjectStorage returns the object storage for the given namespace and object type +func (osr *ObjectStorageRegistry) ObjectStorage(ns string, obj any, backend *contractBackend) (ObjectStorage, error) { + types, ok := osr.contracts[ns] + if !ok { + return nil, errors.Wrapf(ErrObjectStorageNotRegistered, "namespace: %s", ns) + } + contractIndex, ok := types[reflect.TypeOf(obj)] + if !ok { + return nil, errors.Wrapf(ErrObjectStorageNotRegistered, "namespace: %s, object: %T", ns, obj) + } + // TODO: cache storage + switch systemContractTypes[contractIndex] { + case accountStorageType: + return newAccountStorage( + common.BytesToAddress(systemContracts[AccountInfoContractIndex].Address.Bytes()), + backend, + ) + case namespaceStorageContractType: + contractAddr := systemContracts[contractIndex].Address + contract, err := systemcontracts.NewGenericStorageContract(common.BytesToAddress(contractAddr.Bytes()[:]), backend, common.Address(systemContractCreatorAddr)) + if err != nil { + return nil, err + } + return newContractObjectStorage(contract), nil + default: + contractAddr := systemContracts[contractIndex].Address + contract, err := systemcontracts.NewGenericStorageContract(common.BytesToAddress(contractAddr.Bytes()[:]), backend, common.Address(systemContractCreatorAddr)) + if err != nil { + return nil, err + } + return newContractObjectStorage(contract), nil + } +} + +// RegisterAccount registers an account object storage +func (osr *ObjectStorageRegistry) RegisterAccount(ns string, obj any) error { + return osr.register(ns, obj, AccountIndex) +} + +// RegisterStakingBuckets registers a staking buckets object storage +func (osr *ObjectStorageRegistry) RegisterStakingBuckets(ns string, obj systemcontracts.GenericStorageContract) error { + return osr.register(ns, obj, StakingBucketsContractIndex) +} + +// RegisterBucketPool registers a bucket pool object storage +func (osr *ObjectStorageRegistry) RegisterBucketPool(ns string, obj systemcontracts.GenericStorageContract) error { + return osr.register(ns, obj, BucketPoolContractIndex) +} + +// RegisterBucketIndices registers a bucket indices object storage +func (osr *ObjectStorageRegistry) RegisterBucketIndices(ns string, obj systemcontracts.GenericStorageContract) error { + return osr.register(ns, obj, BucketIndicesContractIndex) +} + +// RegisterEndorsement registers an endorsement object storage +func (osr *ObjectStorageRegistry) RegisterEndorsement(ns string, obj systemcontracts.GenericStorageContract) error { + return osr.register(ns, obj, EndorsementContractIndex) +} + +// RegisterCandidateMap registers a candidate map object storage +func (osr *ObjectStorageRegistry) RegisterCandidateMap(ns string, obj systemcontracts.GenericStorageContract) error { + return osr.register(ns, obj, CandidateMapContractIndex) +} + +// RegisterCandidates registers a candidates object storage +func (osr *ObjectStorageRegistry) RegisterCandidates(ns string, obj systemcontracts.GenericStorageContract) error { + return osr.register(ns, obj, CandidatesContractIndex) +} + +// RegisterPollCandidateList registers a poll candidate list object storage +func (osr *ObjectStorageRegistry) RegisterPollCandidateList(ns string, obj systemcontracts.GenericStorageContract) error { + return osr.register(ns, obj, PollCandidateListContractIndex) +} + +// RegisterPollLegacyCandidateList registers a poll legacy candidate list object storage +func (osr *ObjectStorageRegistry) RegisterPollLegacyCandidateList(ns string, obj systemcontracts.GenericStorageContract) error { + return osr.register(ns, obj, PollLegacyCandidateListContractIndex) +} + +// RegisterPollProbationList registers a poll probation list object storage +func (osr *ObjectStorageRegistry) RegisterPollProbationList(ns string, obj systemcontracts.GenericStorageContract) error { + return osr.register(ns, obj, PollProbationListContractIndex) +} + +// RegisterPollUnproductiveDelegate registers a poll unproductive delegate object storage +func (osr *ObjectStorageRegistry) RegisterPollUnproductiveDelegate(ns string, obj systemcontracts.GenericStorageContract) error { + return osr.register(ns, obj, PollUnproductiveDelegateContractIndex) +} + +// RegisterPollBlockMeta registers a poll block meta object storage +func (osr *ObjectStorageRegistry) RegisterPollBlockMeta(ns string, obj systemcontracts.GenericStorageContract) error { + return osr.register(ns, obj, PollBlockMetaContractIndex) +} + +// RegisterRewardingV1 registers a rewarding v1 object storage +func (osr *ObjectStorageRegistry) RegisterRewardingV1(ns string, obj systemcontracts.GenericStorageContract) error { + return osr.register(ns, obj, RewardingContractV1Index) +} + +// RegisterRewardingV2 registers a rewarding v2 object storage +func (osr *ObjectStorageRegistry) RegisterRewardingV2(ns string, obj systemcontracts.GenericStorageContract) error { + return osr.register(ns, obj, RewardingContractV2Index) +} + +// RegisterStakingView registers a staking view object storage +func (osr *ObjectStorageRegistry) RegisterStakingView(ns string, obj systemcontracts.GenericStorageContract) error { + return osr.register(ns, obj, StakingViewContractIndex) +} + +func (osr *ObjectStorageRegistry) register(ns string, obj any, index int) error { + types, ok := osr.contracts[ns] + if !ok { + osr.contracts[ns] = make(map[reflect.Type]int) + types = osr.contracts[ns] + } + if registered, exists := types[reflect.TypeOf(obj)]; exists { + return errors.Wrapf(ErrObjectStorageAlreadyRegistered, "registered: %v", registered) + } + types[reflect.TypeOf(obj)] = index + return nil +} diff --git a/state/factory/erigonstore/systemcontracts.go b/state/factory/erigonstore/systemcontracts.go index 6d34027d74..c9a627b9bf 100644 --- a/state/factory/erigonstore/systemcontracts.go +++ b/state/factory/erigonstore/systemcontracts.go @@ -8,8 +8,9 @@ import ( "github.com/erigontech/erigon-lib/crypto" "github.com/iotexproject/go-pkgs/hash" "github.com/iotexproject/iotex-address/address" - "github.com/iotexproject/iotex-core/v2/systemcontracts" "github.com/pkg/errors" + + "github.com/iotexproject/iotex-core/v2/systemcontracts" ) // SystemContract represents a system contract with its address and bytecode @@ -19,6 +20,8 @@ type SystemContract struct { } const ( + // AccountIndex is the system contract for account storage + AccountIndex = -1 // StakingBucketsContractIndex is the system contract for staking buckets storage StakingBucketsContractIndex int = iota // BucketPoolContractIndex is the system contract for bucket pool storage @@ -56,10 +59,12 @@ const ( const ( defaultSystemContractType = iota namespaceStorageContractType + accountStorageType ) var systemContractTypes = map[int]int{ StakingViewContractIndex: namespaceStorageContractType, + AccountIndex: accountStorageType, } // systemContracts holds all system contracts diff --git a/state/factory/erigonstore/workingsetstore_erigon.go b/state/factory/erigonstore/workingsetstore_erigon.go index bbe17b068e..62f482444c 100644 --- a/state/factory/erigonstore/workingsetstore_erigon.go +++ b/state/factory/erigonstore/workingsetstore_erigon.go @@ -22,7 +22,6 @@ import ( "go.uber.org/zap" "github.com/iotexproject/go-pkgs/hash" - "github.com/iotexproject/iotex-address/address" "github.com/iotexproject/iotex-core/v2/action/protocol" "github.com/iotexproject/iotex-core/v2/action/protocol/execution/evm" @@ -30,7 +29,6 @@ import ( "github.com/iotexproject/iotex-core/v2/db" "github.com/iotexproject/iotex-core/v2/pkg/log" "github.com/iotexproject/iotex-core/v2/state" - "github.com/iotexproject/iotex-core/v2/systemcontracts" ) const ( @@ -431,26 +429,14 @@ func (store *ErigonWorkingSetStore) StateReader() erigonstate.StateReader { } func (store *ErigonWorkingSetStore) NewObjectStorage(ns string, obj any) (ObjectStorage, error) { - var contractAddr address.Address - switch ns { - case "Account": - if _, ok := obj.(*state.Account); !ok { - return nil, nil - } - return newAccountStorage( - common.BytesToAddress(systemContracts[AccountInfoContractIndex].Address.Bytes()), - store.backend, - ) - case "BlockMeta": - contractAddr = systemContracts[PollBlockMetaContractIndex].Address - default: + cs, err := storageRegistry.ObjectStorage(ns, obj, store.backend) + switch errors.Cause(err) { + case nil: + return cs, nil + case ErrObjectStorageNotRegistered: // TODO: fail unknown namespace return nil, nil - } - // TODO: cache storage - contract, err := systemcontracts.NewGenericStorageContract(common.BytesToAddress(contractAddr.Bytes()[:]), store.backend, common.Address(systemContractCreatorAddr)) - if err != nil { + default: return nil, err } - return newContractObjectStorage(contract), nil } From dfd1c27e918a0ddc11fb30c15b82545345b65826 Mon Sep 17 00:00:00 2001 From: envestcc Date: Thu, 25 Sep 2025 18:16:53 +0800 Subject: [PATCH 24/26] fix registry --- state/factory/erigonstore/registry.go | 28 +++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/state/factory/erigonstore/registry.go b/state/factory/erigonstore/registry.go index 7ad83ef4f2..7623f1c30e 100644 --- a/state/factory/erigonstore/registry.go +++ b/state/factory/erigonstore/registry.go @@ -85,72 +85,72 @@ func (osr *ObjectStorageRegistry) RegisterAccount(ns string, obj any) error { } // RegisterStakingBuckets registers a staking buckets object storage -func (osr *ObjectStorageRegistry) RegisterStakingBuckets(ns string, obj systemcontracts.GenericStorageContract) error { +func (osr *ObjectStorageRegistry) RegisterStakingBuckets(ns string, obj systemcontracts.GenericValueContainer) error { return osr.register(ns, obj, StakingBucketsContractIndex) } // RegisterBucketPool registers a bucket pool object storage -func (osr *ObjectStorageRegistry) RegisterBucketPool(ns string, obj systemcontracts.GenericStorageContract) error { +func (osr *ObjectStorageRegistry) RegisterBucketPool(ns string, obj systemcontracts.GenericValueContainer) error { return osr.register(ns, obj, BucketPoolContractIndex) } // RegisterBucketIndices registers a bucket indices object storage -func (osr *ObjectStorageRegistry) RegisterBucketIndices(ns string, obj systemcontracts.GenericStorageContract) error { +func (osr *ObjectStorageRegistry) RegisterBucketIndices(ns string, obj systemcontracts.GenericValueContainer) error { return osr.register(ns, obj, BucketIndicesContractIndex) } // RegisterEndorsement registers an endorsement object storage -func (osr *ObjectStorageRegistry) RegisterEndorsement(ns string, obj systemcontracts.GenericStorageContract) error { +func (osr *ObjectStorageRegistry) RegisterEndorsement(ns string, obj systemcontracts.GenericValueContainer) error { return osr.register(ns, obj, EndorsementContractIndex) } // RegisterCandidateMap registers a candidate map object storage -func (osr *ObjectStorageRegistry) RegisterCandidateMap(ns string, obj systemcontracts.GenericStorageContract) error { +func (osr *ObjectStorageRegistry) RegisterCandidateMap(ns string, obj systemcontracts.GenericValueContainer) error { return osr.register(ns, obj, CandidateMapContractIndex) } // RegisterCandidates registers a candidates object storage -func (osr *ObjectStorageRegistry) RegisterCandidates(ns string, obj systemcontracts.GenericStorageContract) error { +func (osr *ObjectStorageRegistry) RegisterCandidates(ns string, obj systemcontracts.GenericValueContainer) error { return osr.register(ns, obj, CandidatesContractIndex) } // RegisterPollCandidateList registers a poll candidate list object storage -func (osr *ObjectStorageRegistry) RegisterPollCandidateList(ns string, obj systemcontracts.GenericStorageContract) error { +func (osr *ObjectStorageRegistry) RegisterPollCandidateList(ns string, obj systemcontracts.GenericValueContainer) error { return osr.register(ns, obj, PollCandidateListContractIndex) } // RegisterPollLegacyCandidateList registers a poll legacy candidate list object storage -func (osr *ObjectStorageRegistry) RegisterPollLegacyCandidateList(ns string, obj systemcontracts.GenericStorageContract) error { +func (osr *ObjectStorageRegistry) RegisterPollLegacyCandidateList(ns string, obj systemcontracts.GenericValueContainer) error { return osr.register(ns, obj, PollLegacyCandidateListContractIndex) } // RegisterPollProbationList registers a poll probation list object storage -func (osr *ObjectStorageRegistry) RegisterPollProbationList(ns string, obj systemcontracts.GenericStorageContract) error { +func (osr *ObjectStorageRegistry) RegisterPollProbationList(ns string, obj systemcontracts.GenericValueContainer) error { return osr.register(ns, obj, PollProbationListContractIndex) } // RegisterPollUnproductiveDelegate registers a poll unproductive delegate object storage -func (osr *ObjectStorageRegistry) RegisterPollUnproductiveDelegate(ns string, obj systemcontracts.GenericStorageContract) error { +func (osr *ObjectStorageRegistry) RegisterPollUnproductiveDelegate(ns string, obj systemcontracts.GenericValueContainer) error { return osr.register(ns, obj, PollUnproductiveDelegateContractIndex) } // RegisterPollBlockMeta registers a poll block meta object storage -func (osr *ObjectStorageRegistry) RegisterPollBlockMeta(ns string, obj systemcontracts.GenericStorageContract) error { +func (osr *ObjectStorageRegistry) RegisterPollBlockMeta(ns string, obj systemcontracts.GenericValueContainer) error { return osr.register(ns, obj, PollBlockMetaContractIndex) } // RegisterRewardingV1 registers a rewarding v1 object storage -func (osr *ObjectStorageRegistry) RegisterRewardingV1(ns string, obj systemcontracts.GenericStorageContract) error { +func (osr *ObjectStorageRegistry) RegisterRewardingV1(ns string, obj systemcontracts.GenericValueContainer) error { return osr.register(ns, obj, RewardingContractV1Index) } // RegisterRewardingV2 registers a rewarding v2 object storage -func (osr *ObjectStorageRegistry) RegisterRewardingV2(ns string, obj systemcontracts.GenericStorageContract) error { +func (osr *ObjectStorageRegistry) RegisterRewardingV2(ns string, obj systemcontracts.GenericValueContainer) error { return osr.register(ns, obj, RewardingContractV2Index) } // RegisterStakingView registers a staking view object storage -func (osr *ObjectStorageRegistry) RegisterStakingView(ns string, obj systemcontracts.GenericStorageContract) error { +func (osr *ObjectStorageRegistry) RegisterStakingView(ns string, obj systemcontracts.GenericValueContainer) error { return osr.register(ns, obj, StakingViewContractIndex) } From 08cf2b9b767ab1b0f4911b727ee9d34c9810b913 Mon Sep 17 00:00:00 2001 From: envestcc Date: Thu, 21 Aug 2025 17:48:15 +0800 Subject: [PATCH 25/26] store rewarding --- action/protocol/rewarding/admin.go | 41 +++++++++++++++++++++++++ action/protocol/rewarding/fund.go | 23 ++++++++++++++ action/protocol/rewarding/protocol.go | 23 ++------------ action/protocol/rewarding/reward.go | 43 +++++++++++++++++++++++++-- pkg/util/assertions/must.go | 6 ++++ 5 files changed, 114 insertions(+), 22 deletions(-) diff --git a/action/protocol/rewarding/admin.go b/action/protocol/rewarding/admin.go index 47b2302030..f388f6c9ee 100644 --- a/action/protocol/rewarding/admin.go +++ b/action/protocol/rewarding/admin.go @@ -13,9 +13,14 @@ import ( "google.golang.org/protobuf/proto" "github.com/iotexproject/iotex-address/address" + "github.com/iotexproject/iotex-core/v2/action/protocol" "github.com/iotexproject/iotex-core/v2/action/protocol/rewarding/rewardingpb" "github.com/iotexproject/iotex-core/v2/blockchain/genesis" + "github.com/iotexproject/iotex-core/v2/pkg/util/assertions" + "github.com/iotexproject/iotex-core/v2/state" + "github.com/iotexproject/iotex-core/v2/state/factory/erigonstore" + "github.com/iotexproject/iotex-core/v2/systemcontracts" ) // admin stores the admin data of the rewarding protocol @@ -29,6 +34,14 @@ type admin struct { productivityThreshold uint64 } +func init() { + registry := erigonstore.GetObjectStorageRegistry() + assertions.MustNoError(registry.RegisterRewardingV1(state.AccountKVNamespace, &admin{})) + assertions.MustNoError(registry.RegisterRewardingV1(state.AccountKVNamespace, &exempt{})) + assertions.MustNoError(registry.RegisterRewardingV2(_v2RewardingNamespace, &admin{})) + assertions.MustNoError(registry.RegisterRewardingV2(_v2RewardingNamespace, &exempt{})) +} + // Serialize serializes admin state into bytes func (a admin) Serialize() ([]byte, error) { gen := rewardingpb.Admin{ @@ -71,6 +84,20 @@ func (a *admin) Deserialize(data []byte) error { return nil } +func (a *admin) Encode() (systemcontracts.GenericValue, error) { + data, err := a.Serialize() + if err != nil { + return systemcontracts.GenericValue{}, err + } + return systemcontracts.GenericValue{ + AuxiliaryData: data, + }, nil +} + +func (a *admin) Decode(v systemcontracts.GenericValue) error { + return a.Deserialize(v.AuxiliaryData) +} + func (a *admin) grantFoundationBonus(epoch uint64) bool { return epoch <= a.foundationBonusLastEpoch } @@ -106,6 +133,20 @@ func (e *exempt) Deserialize(data []byte) error { return nil } +func (e *exempt) Encode() (systemcontracts.GenericValue, error) { + data, err := e.Serialize() + if err != nil { + return systemcontracts.GenericValue{}, err + } + return systemcontracts.GenericValue{ + AuxiliaryData: data, + }, nil +} + +func (e *exempt) Decode(v systemcontracts.GenericValue) error { + return e.Deserialize(v.AuxiliaryData) +} + // CreateGenesisStates initializes the rewarding protocol by setting the original admin, block and epoch reward func (p *Protocol) CreateGenesisStates( ctx context.Context, diff --git a/action/protocol/rewarding/fund.go b/action/protocol/rewarding/fund.go index dbd6a3048b..95bbc49d0f 100644 --- a/action/protocol/rewarding/fund.go +++ b/action/protocol/rewarding/fund.go @@ -19,7 +19,10 @@ import ( "github.com/iotexproject/iotex-core/v2/action/protocol" accountutil "github.com/iotexproject/iotex-core/v2/action/protocol/account/util" "github.com/iotexproject/iotex-core/v2/action/protocol/rewarding/rewardingpb" + "github.com/iotexproject/iotex-core/v2/pkg/util/assertions" "github.com/iotexproject/iotex-core/v2/state" + "github.com/iotexproject/iotex-core/v2/state/factory/erigonstore" + "github.com/iotexproject/iotex-core/v2/systemcontracts" ) // fund stores the balance of the rewarding fund. The difference between total and available balance should be @@ -29,6 +32,12 @@ type fund struct { unclaimedBalance *big.Int } +func init() { + registry := erigonstore.GetObjectStorageRegistry() + assertions.MustNoError(registry.RegisterRewardingV1(state.AccountKVNamespace, &fund{})) + assertions.MustNoError(registry.RegisterRewardingV2(_v2RewardingNamespace, &fund{})) +} + // Serialize serializes fund state into bytes func (f fund) Serialize() ([]byte, error) { gen := rewardingpb.Fund{ @@ -57,6 +66,20 @@ func (f *fund) Deserialize(data []byte) error { return nil } +func (f *fund) Encode() (systemcontracts.GenericValue, error) { + data, err := f.Serialize() + if err != nil { + return systemcontracts.GenericValue{}, err + } + return systemcontracts.GenericValue{ + AuxiliaryData: data, + }, nil +} + +func (f *fund) Decode(v systemcontracts.GenericValue) error { + return f.Deserialize(v.AuxiliaryData) +} + // Deposit deposits token into the rewarding fund func (p *Protocol) Deposit( ctx context.Context, diff --git a/action/protocol/rewarding/protocol.go b/action/protocol/rewarding/protocol.go index 8375a45ace..4ed8190582 100644 --- a/action/protocol/rewarding/protocol.go +++ b/action/protocol/rewarding/protocol.go @@ -138,7 +138,7 @@ func (p *Protocol) migrateValue(sm protocol.StateManager, key []byte, value inte if err := p.putStateV2(sm, key, value); err != nil { return err } - return p.deleteStateV1(sm, key) + return p.deleteStateV1(sm, key, value) } func (p *Protocol) setFoundationBonusExtension(ctx context.Context, sm protocol.StateManager) error { @@ -359,26 +359,9 @@ func (p *Protocol) putStateV2(sm protocol.StateManager, key []byte, value interf return err } -func (p *Protocol) deleteState(ctx context.Context, sm protocol.StateManager, key []byte) error { - if useV2Storage(ctx) { - return p.deleteStateV2(sm, key) - } - return p.deleteStateV1(sm, key) -} - -func (p *Protocol) deleteStateV1(sm protocol.StateManager, key []byte) error { +func (p *Protocol) deleteStateV1(sm protocol.StateManager, key []byte, obj any) error { keyHash := hash.Hash160b(append(p.keyPrefix, key...)) - _, err := sm.DelState(protocol.LegacyKeyOption(keyHash)) - if errors.Cause(err) == state.ErrStateNotExist { - // don't care if not exist - return nil - } - return err -} - -func (p *Protocol) deleteStateV2(sm protocol.StateManager, key []byte) error { - k := append(p.keyPrefix, key...) - _, err := sm.DelState(protocol.KeyOption(k), protocol.NamespaceOption(_v2RewardingNamespace)) + _, err := sm.DelState(protocol.LegacyKeyOption(keyHash), protocol.ObjectOption(obj)) if errors.Cause(err) == state.ErrStateNotExist { // don't care if not exist return nil diff --git a/action/protocol/rewarding/reward.go b/action/protocol/rewarding/reward.go index 67f58ee258..76346217b3 100644 --- a/action/protocol/rewarding/reward.go +++ b/action/protocol/rewarding/reward.go @@ -25,12 +25,23 @@ import ( "github.com/iotexproject/iotex-core/v2/action/protocol/staking" "github.com/iotexproject/iotex-core/v2/pkg/enc" "github.com/iotexproject/iotex-core/v2/pkg/log" + "github.com/iotexproject/iotex-core/v2/pkg/util/assertions" "github.com/iotexproject/iotex-core/v2/state" + "github.com/iotexproject/iotex-core/v2/state/factory/erigonstore" + "github.com/iotexproject/iotex-core/v2/systemcontracts" ) // rewardHistory is the dummy struct to record a reward. Only key matters. type rewardHistory struct{} +func init() { + registry := erigonstore.GetObjectStorageRegistry() + assertions.MustNoError(registry.RegisterRewardingV1(state.AccountKVNamespace, &rewardHistory{})) + assertions.MustNoError(registry.RegisterRewardingV1(state.AccountKVNamespace, &rewardAccount{})) + assertions.MustNoError(registry.RegisterRewardingV2(_v2RewardingNamespace, &rewardHistory{})) + assertions.MustNoError(registry.RegisterRewardingV2(_v2RewardingNamespace, &rewardAccount{})) +} + // Serialize serializes reward history state into bytes func (b rewardHistory) Serialize() ([]byte, error) { gen := rewardingpb.RewardHistory{} @@ -40,6 +51,20 @@ func (b rewardHistory) Serialize() ([]byte, error) { // Deserialize deserializes bytes into reward history state func (b *rewardHistory) Deserialize(data []byte) error { return nil } +func (b *rewardHistory) Encode() (systemcontracts.GenericValue, error) { + data, err := b.Serialize() + if err != nil { + return systemcontracts.GenericValue{}, err + } + return systemcontracts.GenericValue{ + AuxiliaryData: data, + }, nil +} + +func (b *rewardHistory) Decode(v systemcontracts.GenericValue) error { + return b.Deserialize(v.AuxiliaryData) +} + // rewardAccount stores the unclaimed balance of an account type rewardAccount struct { balance *big.Int @@ -67,6 +92,20 @@ func (a *rewardAccount) Deserialize(data []byte) error { return nil } +func (a *rewardAccount) Encode() (systemcontracts.GenericValue, error) { + data, err := a.Serialize() + if err != nil { + return systemcontracts.GenericValue{}, err + } + return systemcontracts.GenericValue{ + AuxiliaryData: data, + }, nil +} + +func (a *rewardAccount) Decode(v systemcontracts.GenericValue) error { + return a.Deserialize(v.AuxiliaryData) +} + // GrantBlockReward grants the block reward (token) to the block producer func (p *Protocol) GrantBlockReward( ctx context.Context, @@ -389,7 +428,7 @@ func (p *Protocol) grantToAccount(ctx context.Context, sm protocol.StateManager, // entry exist // check if from legacy, and we have started using v2, delete v1 if fromLegacy && useV2Storage(ctx) { - if err := p.deleteStateV1(sm, accKey); err != nil { + if err := p.deleteStateV1(sm, accKey, &rewardAccount{}); err != nil { return err } } @@ -416,7 +455,7 @@ func (p *Protocol) claimFromAccount(ctx context.Context, sm protocol.StateManage return err } if fromLegacy && useV2Storage(ctx) { - if err := p.deleteStateV1(sm, accKey); err != nil { + if err := p.deleteStateV1(sm, accKey, &rewardAccount{}); err != nil { return err } } diff --git a/pkg/util/assertions/must.go b/pkg/util/assertions/must.go index 5a6e6e91f8..0f83d5fe14 100644 --- a/pkg/util/assertions/must.go +++ b/pkg/util/assertions/must.go @@ -1,5 +1,11 @@ package assertions +func MustNoError(err error) { + if err != nil { + panic(err) + } +} + func MustNoErrorV[V any](v V, err error) V { if err != nil { panic(err) From fbab5ea82b6f3e7feee050223071f8bedc418dc9 Mon Sep 17 00:00:00 2001 From: envestcc Date: Thu, 21 Aug 2025 17:59:41 +0800 Subject: [PATCH 26/26] store poll --- action/protocol/poll/blockmeta.go | 22 +++++++++ action/protocol/poll/util.go | 5 ++- action/protocol/vote/probationlist.go | 23 ++++++++++ action/protocol/vote/unproductivedelegate.go | 21 +++++++++ state/candidate.go | 16 +++++++ state/factory/erigonstore/iterator.go | 47 ++++++++++++++++++++ state/factory/erigonstore/objectstorage.go | 4 +- state/factory/erigonstore/registry.go | 9 ++-- systemcontracts/storage.go | 42 ----------------- 9 files changed, 138 insertions(+), 51 deletions(-) create mode 100644 state/factory/erigonstore/iterator.go diff --git a/action/protocol/poll/blockmeta.go b/action/protocol/poll/blockmeta.go index 370e1de590..13ae8fd2e4 100644 --- a/action/protocol/poll/blockmeta.go +++ b/action/protocol/poll/blockmeta.go @@ -12,7 +12,11 @@ import ( "google.golang.org/protobuf/proto" "google.golang.org/protobuf/types/known/timestamppb" + "github.com/iotexproject/iotex-core/v2/action/protocol" "github.com/iotexproject/iotex-core/v2/action/protocol/poll/blockmetapb" + "github.com/iotexproject/iotex-core/v2/pkg/util/assertions" + "github.com/iotexproject/iotex-core/v2/state/factory/erigonstore" + "github.com/iotexproject/iotex-core/v2/systemcontracts" ) // BlockMeta is a struct to store block metadata @@ -22,6 +26,10 @@ type BlockMeta struct { MintTime time.Time } +func init() { + assertions.MustNoError(erigonstore.GetObjectStorageRegistry().RegisterPollBlockMeta(protocol.SystemNamespace, &BlockMeta{})) +} + // NewBlockMeta constructs new blockmeta struct with given fieldss func NewBlockMeta(height uint64, producer string, mintTime time.Time) *BlockMeta { return &BlockMeta{ @@ -70,3 +78,17 @@ func (bm *BlockMeta) LoadProto(pb *blockmetapb.BlockMeta) error { bm.MintTime = mintTime.UTC() return nil } + +// Encode encodes BlockMeta into a GenericValue +func (bm *BlockMeta) Encode() (systemcontracts.GenericValue, error) { + data, err := bm.Serialize() + if err != nil { + return systemcontracts.GenericValue{}, errors.Wrap(err, "failed to serialize block meta") + } + return systemcontracts.GenericValue{PrimaryData: data}, nil +} + +// Decode decodes a GenericValue into BlockMeta +func (bm *BlockMeta) Decode(data systemcontracts.GenericValue) error { + return bm.Deserialize(data.PrimaryData) +} diff --git a/action/protocol/poll/util.go b/action/protocol/poll/util.go index f66a052b87..9f0e5656f4 100644 --- a/action/protocol/poll/util.go +++ b/action/protocol/poll/util.go @@ -271,7 +271,7 @@ func shiftCandidates(sm protocol.StateManager) (uint64, error) { if stateHeight != putStateHeight { return 0, errors.Wrap(ErrInconsistentHeight, "failed to shift candidates") } - if delStateHeight, err = sm.DelState(protocol.KeyOption(nextKey[:]), protocol.NamespaceOption(protocol.SystemNamespace)); err != nil { + if delStateHeight, err = sm.DelState(protocol.KeyOption(nextKey[:]), protocol.NamespaceOption(protocol.SystemNamespace), protocol.ObjectOption(&state.CandidateList{})); err != nil { return 0, errors.Wrap( err, "failed to delete next candidatelist after shifting", @@ -306,7 +306,7 @@ func shiftProbationList(sm protocol.StateManager) (uint64, error) { if stateHeight != putStateHeight { return 0, errors.Wrap(ErrInconsistentHeight, "failed to shift candidates") } - if delStateHeight, err = sm.DelState(protocol.KeyOption(nextKey[:]), protocol.NamespaceOption(protocol.SystemNamespace)); err != nil { + if delStateHeight, err = sm.DelState(protocol.KeyOption(nextKey[:]), protocol.NamespaceOption(protocol.SystemNamespace), protocol.ObjectOption(&vote.ProbationList{})); err != nil { return 0, errors.Wrap( err, "failed to delete next probationlist after shifting", @@ -341,6 +341,7 @@ func allBlockMetasFromDB(sr protocol.StateReader, blocksInEpoch uint64) ([]*Bloc protocol.KeysOption(func() ([][]byte, error) { return keys, nil }), + protocol.ObjectOption(&BlockMeta{}), ) if err != nil { return nil, err diff --git a/action/protocol/vote/probationlist.go b/action/protocol/vote/probationlist.go index 97bb33d5ff..8cd8029e0e 100644 --- a/action/protocol/vote/probationlist.go +++ b/action/protocol/vote/probationlist.go @@ -12,6 +12,11 @@ import ( "google.golang.org/protobuf/proto" "github.com/iotexproject/iotex-proto/golang/iotextypes" + + "github.com/iotexproject/iotex-core/v2/action/protocol" + "github.com/iotexproject/iotex-core/v2/pkg/util/assertions" + "github.com/iotexproject/iotex-core/v2/state/factory/erigonstore" + "github.com/iotexproject/iotex-core/v2/systemcontracts" ) // ProbationList defines a map where key is candidate's name and value is the counter which counts the unproductivity during probation epoch. @@ -20,6 +25,10 @@ type ProbationList struct { IntensityRate uint32 } +func init() { + assertions.MustNoError(erigonstore.GetObjectStorageRegistry().RegisterPollProbationList(protocol.SystemNamespace, &ProbationList{})) +} + // NewProbationList returns a new probation list func NewProbationList(intensity uint32) *ProbationList { return &ProbationList{ @@ -74,3 +83,17 @@ func (pl *ProbationList) LoadProto(probationListpb *iotextypes.ProbationCandidat return nil } + +// New creates a new instance of ProbationList +func (pl *ProbationList) Encode() (systemcontracts.GenericValue, error) { + data, err := pl.Serialize() + if err != nil { + return systemcontracts.GenericValue{}, err + } + return systemcontracts.GenericValue{PrimaryData: data}, nil +} + +// Decode decodes a GenericValue into ProbationList +func (pl *ProbationList) Decode(data systemcontracts.GenericValue) error { + return pl.Deserialize(data.PrimaryData) +} diff --git a/action/protocol/vote/unproductivedelegate.go b/action/protocol/vote/unproductivedelegate.go index f1f8914d91..7822b690b4 100644 --- a/action/protocol/vote/unproductivedelegate.go +++ b/action/protocol/vote/unproductivedelegate.go @@ -11,7 +11,11 @@ import ( "github.com/pkg/errors" "google.golang.org/protobuf/proto" + "github.com/iotexproject/iotex-core/v2/action/protocol" updpb "github.com/iotexproject/iotex-core/v2/action/protocol/vote/unproductivedelegatepb" + "github.com/iotexproject/iotex-core/v2/pkg/util/assertions" + "github.com/iotexproject/iotex-core/v2/state/factory/erigonstore" + "github.com/iotexproject/iotex-core/v2/systemcontracts" ) // UnproductiveDelegate defines unproductive delegates information within probation period @@ -21,6 +25,10 @@ type UnproductiveDelegate struct { cacheSize uint64 } +func init() { + assertions.MustNoError(erigonstore.GetObjectStorageRegistry().RegisterPollUnproductiveDelegate(protocol.SystemNamespace, &UnproductiveDelegate{})) +} + // NewUnproductiveDelegate creates new UnproductiveDelegate with probationperiod and cacheSize func NewUnproductiveDelegate(probationPeriod uint64, cacheSize uint64) (*UnproductiveDelegate, error) { if probationPeriod > cacheSize { @@ -124,3 +132,16 @@ func (upd *UnproductiveDelegate) Equal(upd2 *UnproductiveDelegate) bool { func (upd *UnproductiveDelegate) DelegateList() [][]string { return upd.delegatelist } + +// New creates a new instance of UnproductiveDelegate +func (upd *UnproductiveDelegate) Encode() (systemcontracts.GenericValue, error) { + data, err := upd.Serialize() + if err != nil { + return systemcontracts.GenericValue{}, err + } + return systemcontracts.GenericValue{PrimaryData: data}, nil +} + +func (upd *UnproductiveDelegate) Decode(data systemcontracts.GenericValue) error { + return upd.Deserialize(data.PrimaryData) +} diff --git a/state/candidate.go b/state/candidate.go index e26ba3b9bd..286f0ee3e9 100644 --- a/state/candidate.go +++ b/state/candidate.go @@ -15,6 +15,8 @@ import ( "github.com/pkg/errors" "google.golang.org/protobuf/proto" + "github.com/iotexproject/iotex-core/v2/systemcontracts" + "github.com/iotexproject/iotex-address/address" ) @@ -150,6 +152,20 @@ func (l *CandidateList) LoadProto(candList *iotextypes.CandidateList) error { return nil } +// Encode encodes a CandidateList into a GenericValue +func (l *CandidateList) Encode() (systemcontracts.GenericValue, error) { + data, err := l.Serialize() + if err != nil { + return systemcontracts.GenericValue{}, err + } + return systemcontracts.GenericValue{PrimaryData: data}, nil +} + +// Decode decodes a GenericValue into CandidateList +func (l *CandidateList) Decode(data systemcontracts.GenericValue) error { + return l.Deserialize(data.PrimaryData) +} + // candidateToPb converts a candidate to protobuf's candidate message func candidateToPb(cand *Candidate) *iotextypes.Candidate { candidatePb := &iotextypes.Candidate{ diff --git a/state/factory/erigonstore/iterator.go b/state/factory/erigonstore/iterator.go new file mode 100644 index 0000000000..c89498e554 --- /dev/null +++ b/state/factory/erigonstore/iterator.go @@ -0,0 +1,47 @@ +package erigonstore + +import ( + "github.com/iotexproject/iotex-core/v2/state" + "github.com/iotexproject/iotex-core/v2/systemcontracts" +) + +// GenericValueObjectIterator is an iterator for GenericValue objects +type GenericValueObjectIterator struct { + keys [][]byte + values []systemcontracts.GenericValue + exists []bool + cur int +} + +// NewGenericValueObjectIterator creates a new GenericValueObjectIterator +func NewGenericValueObjectIterator(keys [][]byte, values []systemcontracts.GenericValue, exists []bool) (*GenericValueObjectIterator, error) { + return &GenericValueObjectIterator{ + keys: keys, + values: values, + exists: exists, + cur: 0, + }, nil +} + +// Size returns the size of the iterator +func (gvoi *GenericValueObjectIterator) Size() int { + return len(gvoi.values) +} + +// Next returns the next key-value pair from the iterator +func (gvoi *GenericValueObjectIterator) Next(o interface{}) ([]byte, error) { + if gvoi.cur >= len(gvoi.values) { + return nil, state.ErrOutOfBoundary + } + value := gvoi.values[gvoi.cur] + key := gvoi.keys[gvoi.cur] + gvoi.cur++ + if gvoi.exists != nil && !gvoi.exists[gvoi.cur] { + gvoi.cur++ + return key, state.ErrNilValue + } + if err := systemcontracts.DecodeGenericValue(o, value); err != nil { + return nil, err + } + return key, nil +} diff --git a/state/factory/erigonstore/objectstorage.go b/state/factory/erigonstore/objectstorage.go index dfc9a7a0b9..216c10d1e1 100644 --- a/state/factory/erigonstore/objectstorage.go +++ b/state/factory/erigonstore/objectstorage.go @@ -69,7 +69,7 @@ func (cos *contractObjectStorage) List() (state.Iterator, error) { return nil, err } - return systemcontracts.NewGenericValueObjectIterator(retval.KeyList, retval.Values, nil) + return NewGenericValueObjectIterator(retval.KeyList, retval.Values, nil) } func (cos *contractObjectStorage) Batch(keys [][]byte) (state.Iterator, error) { @@ -78,7 +78,7 @@ func (cos *contractObjectStorage) Batch(keys [][]byte) (state.Iterator, error) { return nil, err } - return systemcontracts.NewGenericValueObjectIterator(keys, retval.Values, retval.ExistsFlags) + return NewGenericValueObjectIterator(keys, retval.Values, retval.ExistsFlags) } func (cos *contractObjectStorage) Count() (*big.Int, error) { diff --git a/state/factory/erigonstore/registry.go b/state/factory/erigonstore/registry.go index 7623f1c30e..ce50dc8f3f 100644 --- a/state/factory/erigonstore/registry.go +++ b/state/factory/erigonstore/registry.go @@ -5,9 +5,8 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/pkg/errors" - "go.uber.org/zap" - "github.com/iotexproject/iotex-core/v2/pkg/log" + "github.com/iotexproject/iotex-core/v2/pkg/util/assertions" "github.com/iotexproject/iotex-core/v2/state" "github.com/iotexproject/iotex-core/v2/systemcontracts" ) @@ -29,9 +28,9 @@ type ObjectStorageRegistry struct { } func init() { - if err := storageRegistry.RegisterAccount(state.AccountKVNamespace, &state.Account{}); err != nil { - log.L().Panic("failed to register account storage", zap.Error(err)) - } + assertions.MustNoError(storageRegistry.RegisterAccount(state.AccountKVNamespace, &state.Account{})) + assertions.MustNoError(storageRegistry.RegisterPollCandidateList(state.SystemNamespace, &state.CandidateList{})) + assertions.MustNoError(storageRegistry.RegisterPollLegacyCandidateList(state.AccountKVNamespace, &state.CandidateList{})) } // GetObjectStorageRegistry returns the global object storage registry diff --git a/systemcontracts/storage.go b/systemcontracts/storage.go index 278ab80b53..5217b50330 100644 --- a/systemcontracts/storage.go +++ b/systemcontracts/storage.go @@ -4,7 +4,6 @@ import ( "math/big" "github.com/ethereum/go-ethereum/common" - "github.com/iotexproject/iotex-core/v2/state" "github.com/pkg/errors" ) @@ -23,14 +22,6 @@ type ( Encode() (GenericValue, error) } - // GenericValueObjectIterator is an iterator for GenericValue objects - GenericValueObjectIterator struct { - keys [][]byte - values []GenericValue - exists []bool - cur int - } - // BatchGetResult represents the result of a batch get operation BatchGetResult struct { Values []GenericValue `json:"values"` @@ -79,36 +70,3 @@ func DecodeGenericValue(o interface{}, data GenericValue) error { } return errors.New("unsupported object type") } - -// NewGenericValueObjectIterator creates a new GenericValueObjectIterator -func NewGenericValueObjectIterator(keys [][]byte, values []GenericValue, exists []bool) (state.Iterator, error) { - return &GenericValueObjectIterator{ - keys: keys, - values: values, - exists: exists, - cur: 0, - }, nil -} - -// Size returns the size of the iterator -func (gvoi *GenericValueObjectIterator) Size() int { - return len(gvoi.values) -} - -// Next returns the next key-value pair from the iterator -func (gvoi *GenericValueObjectIterator) Next(o interface{}) ([]byte, error) { - if gvoi.cur >= len(gvoi.values) { - return nil, state.ErrOutOfBoundary - } - value := gvoi.values[gvoi.cur] - key := gvoi.keys[gvoi.cur] - gvoi.cur++ - if gvoi.exists != nil && !gvoi.exists[gvoi.cur] { - gvoi.cur++ - return key, state.ErrNilValue - } - if err := DecodeGenericValue(o, value); err != nil { - return nil, err - } - return key, nil -}