diff --git a/clients/apiclient/.openapi-generator/FILES b/clients/apiclient/.openapi-generator/FILES index b36e0ae7a0..3647304ea0 100644 --- a/clients/apiclient/.openapi-generator/FILES +++ b/clients/apiclient/.openapi-generator/FILES @@ -4,6 +4,7 @@ api/openapi.yaml api_auth.go api_chains.go api_corecontracts.go +api_default.go api_metrics.go api_node.go api_requests.go @@ -45,6 +46,7 @@ docs/ControlAddressesResponse.md docs/CorecontractsApi.md docs/DKSharesInfo.md docs/DKSharesPostRequest.md +docs/DefaultApi.md docs/ErrorMessageFormatResponse.md docs/ErrorParameter.md docs/EventsResponse.md @@ -83,6 +85,7 @@ docs/PeeringNodeStatusResponse.md docs/PeeringTrustRequest.md docs/ProtocolParameters.md docs/PublisherStateTransactionItem.md +docs/Ratio32.md docs/ReceiptError.md docs/ReceiptResponse.md docs/RentStructure.md @@ -176,6 +179,7 @@ model_peering_node_status_response.go model_peering_trust_request.go model_protocol_parameters.go model_publisher_state_transaction_item.go +model_ratio32.go model_receipt_error.go model_receipt_response.go model_rent_structure.go diff --git a/clients/apiclient/api/openapi.yaml b/clients/apiclient/api/openapi.yaml index 3930f6c782..62b485bf8e 100644 --- a/clients/apiclient/api/openapi.yaml +++ b/clients/apiclient/api/openapi.yaml @@ -332,8 +332,7 @@ paths: schema: format: string type: string - - description: AgentID (Bech32 for WasmVM | Hex for EVM | '000000@Bech32' Addresses - require urlencode) + - description: AgentID (Bech32 for WasmVM | Hex for EVM) in: path name: agentID required: true @@ -387,8 +386,6 @@ paths: schema: $ref: '#/components/schemas/ValidationError' description: "Unauthorized (Wrong permissions, missing token)" - security: - - Authorization: [] summary: Get all foundries owned by an account tags: - corecontracts @@ -403,8 +400,7 @@ paths: schema: format: string type: string - - description: AgentID (Bech32 for WasmVM | Hex for EVM | '000000@Bech32' Addresses - require urlencode) + - description: AgentID (Bech32 for WasmVM | Hex for EVM) in: path name: agentID required: true @@ -438,8 +434,7 @@ paths: schema: format: string type: string - - description: AgentID (Bech32 for WasmVM | Hex for EVM | '000000@Bech32' Addresses - require urlencode) + - description: AgentID (Bech32 for WasmVM | Hex for EVM) in: path name: agentID required: true @@ -1398,7 +1393,7 @@ paths: schema: format: string type: string - - description: Key (Hex) + - description: State Key (Hex) in: path name: stateKey required: true @@ -1415,23 +1410,6 @@ paths: summary: Fetch the raw value associated with the given key in the chain state tags: - chains - /chains/{chainID}/ws: - get: - operationId: attachToWebsocket - parameters: - - description: ChainID (Bech32) - in: path - name: chainID - required: true - schema: - format: string - type: string - responses: - default: - content: {} - description: successful operation - tags: - - chains /health: get: operationId: getHealth @@ -1704,7 +1682,7 @@ paths: application/json: schema: items: - $ref: '#/components/schemas/PeeringNodeStatusResponse__' + $ref: '#/components/schemas/PeeringNodeStatusResponse_' type: array description: A list of all peers "401": @@ -2079,6 +2057,12 @@ paths: tags: - users x-codegen-request-body-name: "" + /ws: + get: + responses: + default: + content: {} + description: successful operation components: schemas: AccountFoundriesResponse: @@ -2762,8 +2746,13 @@ components: description: description gasFeePolicy: gasFeeTokenId: gasFeeTokenId - gasPerToken: "100" + gasPerToken: + a: 1 + b: 100 validatorFeeShare: 1 + evmGasRatio: + a: 0 + b: 0 isActive: true maxBlobSize: 2000000 maxEventSize: 2000 @@ -2797,7 +2786,7 @@ components: xml: name: EVMChainID gasFeePolicy: - $ref: '#/components/schemas/gasFeePolicy' + $ref: '#/components/schemas/GasFeePolicy' isActive: description: Whether or not the chain is active. format: boolean @@ -3010,18 +2999,18 @@ components: committeeNodes: - node: isAlive: true - peeringURL: peeringURL + peeringURL: localhost:4000 name: name - publicKey: 61270151fbd8c71e43c17e0eff8c76c1ba991be28f088f72a05d790f302d67c7 - numUsers: 6 + publicKey: 0x0000 + numUsers: 1 isTrusted: true accessAPI: accessAPI - node: isAlive: true - peeringURL: peeringURL + peeringURL: localhost:4000 name: name - publicKey: 61270151fbd8c71e43c17e0eff8c76c1ba991be28f088f72a05d790f302d67c7 - numUsers: 6 + publicKey: 0x0000 + numUsers: 1 isTrusted: true accessAPI: accessAPI chainId: tst1pqm5ckama06xhkl080mmvz6l3xy8c8lulrwy7mx4ll0fc69krxfgka70j0e @@ -3127,10 +3116,10 @@ components: example: node: isAlive: true - peeringURL: peeringURL + peeringURL: localhost:4000 name: name - publicKey: 61270151fbd8c71e43c17e0eff8c76c1ba991be28f088f72a05d790f302d67c7 - numUsers: 6 + publicKey: 0x0000 + numUsers: 1 isTrusted: true accessAPI: accessAPI properties: @@ -3666,6 +3655,76 @@ components: type: object xml: name: FoundryOutputResponse + GasFeePolicy: + example: + gasFeeTokenId: gasFeeTokenId + gasPerToken: + a: 1 + b: 100 + validatorFeeShare: 1 + evmGasRatio: + a: 0 + b: 0 + properties: + evmGasRatio: + $ref: '#/components/schemas/Ratio32_' + gasFeeTokenId: + description: The gas fee token id. Empty if base token. + format: string + type: string + xml: + name: GasFeeTokenID + gasPerToken: + $ref: '#/components/schemas/Ratio32' + validatorFeeShare: + description: The validator fee share. + format: int32 + type: integer + xml: + name: ValidatorFeeShare + required: + - evmGasRatio + - gasFeeTokenId + - gasPerToken + - validatorFeeShare + type: object + xml: + name: GasFeePolicy + GasFeePolicy_: + example: + gasFeeTokenId: gasFeeTokenId + gasPerToken: + a: 0 + b: 0 + validatorFeeShare: 0 + evmGasRatio: + a: 0 + b: 0 + properties: + evmGasRatio: + $ref: '#/components/schemas/Ratio32_' + gasFeeTokenId: + description: The gas fee token id. Empty if base token. + format: string + type: string + xml: + name: GasFeeTokenID + gasPerToken: + $ref: '#/components/schemas/Ratio32_' + validatorFeeShare: + description: The validator fee share. + format: int32 + type: integer + xml: + name: ValidatorFeeShare + required: + - evmGasRatio + - gasFeeTokenId + - gasPerToken + - validatorFeeShare + type: object + xml: + name: GasFeePolicy GovAllowedStateControllerAddressesResponse: example: addresses: @@ -3692,8 +3751,13 @@ components: description: description gasFeePolicy: gasFeeTokenId: gasFeeTokenId - gasPerToken: gasPerToken + gasPerToken: + a: 0 + b: 0 validatorFeeShare: 0 + evmGasRatio: + a: 0 + b: 0 maxBlobSize: 6 maxEventSize: 1 properties: @@ -3716,7 +3780,7 @@ components: xml: name: Description gasFeePolicy: - $ref: '#/components/schemas/gasFeePolicy_' + $ref: '#/components/schemas/GasFeePolicy_' maxBlobSize: description: The maximum contract blob size. format: int32 @@ -4506,60 +4570,6 @@ components: xml: name: PeeringNodeStatusResponse PeeringNodeStatusResponse_: - example: - isAlive: true - peeringURL: peeringURL - name: name - publicKey: 61270151fbd8c71e43c17e0eff8c76c1ba991be28f088f72a05d790f302d67c7 - numUsers: 6 - isTrusted: true - properties: - isAlive: - description: Whether or not the peer is activated - format: boolean - type: boolean - xml: - name: IsAlive - isTrusted: - format: boolean - type: boolean - xml: - name: IsTrusted - name: - format: string - type: string - xml: - name: Name - numUsers: - description: The amount of users attached to the peer - format: int32 - type: integer - xml: - name: NumUsers - peeringURL: - description: The peering URL of the peer - format: string - type: string - xml: - name: PeeringURL - publicKey: - description: The peers public key encoded in Hex - example: 61270151fbd8c71e43c17e0eff8c76c1ba991be28f088f72a05d790f302d67c7 - format: string - type: string - xml: - name: PublicKey - required: - - isAlive - - isTrusted - - name - - numUsers - - peeringURL - - publicKey - type: object - xml: - name: PeeringNodeStatusResponse - PeeringNodeStatusResponse__: example: isAlive: true peeringURL: localhost:4000 @@ -4746,6 +4756,54 @@ components: type: object xml: name: PublisherStateTransactionItem + Ratio32: + example: + a: 1 + b: 100 + properties: + a: + example: 1 + format: int32 + minimum: 0 + type: integer + xml: + name: A + b: + example: 100 + format: int32 + minimum: 0 + type: integer + xml: + name: B + required: + - a + - b + type: object + xml: + name: Ratio32 + Ratio32_: + example: + a: 0 + b: 0 + properties: + a: + format: int32 + minimum: 0 + type: integer + xml: + name: A + b: + format: int32 + minimum: 0 + type: integer + xml: + name: B + required: + - a + - b + type: object + xml: + name: Ratio32 ReceiptError: example: contractHName: contractHName @@ -5461,70 +5519,6 @@ components: type: object xml: name: VersionResponse - gasFeePolicy: - example: - gasFeeTokenId: gasFeeTokenId - gasPerToken: "100" - validatorFeeShare: 1 - properties: - gasFeeTokenId: - description: The gas fee token id. Empty if base token. - format: string - type: string - xml: - name: GasFeeTokenID - gasPerToken: - description: The amount of gas per token. (uint64 as string) - example: "100" - format: string - type: string - xml: - name: GasPerToken - validatorFeeShare: - description: The validator fee share. - format: int32 - minimum: 1 - type: integer - xml: - name: ValidatorFeeShare - required: - - gasFeeTokenId - - gasPerToken - - validatorFeeShare - type: object - xml: - name: gasFeePolicy - gasFeePolicy_: - example: - gasFeeTokenId: gasFeeTokenId - gasPerToken: gasPerToken - validatorFeeShare: 0 - properties: - gasFeeTokenId: - description: The gas fee token id. Empty if base token. - format: string - type: string - xml: - name: GasFeeTokenID - gasPerToken: - description: The amount of gas per token. (uint64 as string) - format: string - type: string - xml: - name: GasPerToken - validatorFeeShare: - description: The validator fee share. - format: int32 - type: integer - xml: - name: ValidatorFeeShare - required: - - gasFeeTokenId - - gasPerToken - - validatorFeeShare - type: object - xml: - name: gasFeePolicy securitySchemes: Authorization: description: JWT Token diff --git a/clients/apiclient/api_chains.go b/clients/apiclient/api_chains.go index 18ac76c7d5..75c709aa79 100644 --- a/clients/apiclient/api_chains.go +++ b/clients/apiclient/api_chains.go @@ -255,96 +255,6 @@ func (a *ChainsApiService) AddAccessNodeExecute(r ApiAddAccessNodeRequest) (*htt return localVarHTTPResponse, nil } -type ApiAttachToWebsocketRequest struct { - ctx context.Context - ApiService *ChainsApiService - chainID string -} - -func (r ApiAttachToWebsocketRequest) Execute() (*http.Response, error) { - return r.ApiService.AttachToWebsocketExecute(r) -} - -/* -AttachToWebsocket Method for AttachToWebsocket - - @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). - @param chainID ChainID (Bech32) - @return ApiAttachToWebsocketRequest -*/ -func (a *ChainsApiService) AttachToWebsocket(ctx context.Context, chainID string) ApiAttachToWebsocketRequest { - return ApiAttachToWebsocketRequest{ - ApiService: a, - ctx: ctx, - chainID: chainID, - } -} - -// Execute executes the request -func (a *ChainsApiService) AttachToWebsocketExecute(r ApiAttachToWebsocketRequest) (*http.Response, error) { - var ( - localVarHTTPMethod = http.MethodGet - localVarPostBody interface{} - formFiles []formFile - ) - - localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "ChainsApiService.AttachToWebsocket") - if err != nil { - return nil, &GenericOpenAPIError{error: err.Error()} - } - - localVarPath := localBasePath + "/chains/{chainID}/ws" - localVarPath = strings.Replace(localVarPath, "{"+"chainID"+"}", url.PathEscape(parameterValueToString(r.chainID, "chainID")), -1) - - localVarHeaderParams := make(map[string]string) - localVarQueryParams := url.Values{} - localVarFormParams := url.Values{} - - // to determine the Content-Type header - localVarHTTPContentTypes := []string{} - - // set Content-Type header - localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) - if localVarHTTPContentType != "" { - localVarHeaderParams["Content-Type"] = localVarHTTPContentType - } - - // to determine the Accept header - localVarHTTPHeaderAccepts := []string{} - - // set Accept header - localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) - if localVarHTTPHeaderAccept != "" { - localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept - } - req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) - if err != nil { - return nil, err - } - - localVarHTTPResponse, err := a.client.callAPI(req) - if err != nil || localVarHTTPResponse == nil { - return localVarHTTPResponse, err - } - - localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) - localVarHTTPResponse.Body.Close() - localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) - if err != nil { - return localVarHTTPResponse, err - } - - if localVarHTTPResponse.StatusCode >= 300 { - newErr := &GenericOpenAPIError{ - body: localVarBody, - error: localVarHTTPResponse.Status, - } - return localVarHTTPResponse, newErr - } - - return localVarHTTPResponse, nil -} - type ApiChainsChainIDEvmGetRequest struct { ctx context.Context ApiService *ChainsApiService @@ -1197,7 +1107,7 @@ GetStateValue Fetch the raw value associated with the given key in the chain sta @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). @param chainID ChainID (Bech32) - @param stateKey Key (Hex) + @param stateKey State Key (Hex) @return ApiGetStateValueRequest */ func (a *ChainsApiService) GetStateValue(ctx context.Context, chainID string, stateKey string) ApiGetStateValueRequest { diff --git a/clients/apiclient/api_corecontracts.go b/clients/apiclient/api_corecontracts.go index 40c5f67b65..92a64bda39 100644 --- a/clients/apiclient/api_corecontracts.go +++ b/clients/apiclient/api_corecontracts.go @@ -39,7 +39,7 @@ AccountsGetAccountBalance Get all assets belonging to an account @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). @param chainID ChainID (Bech32) - @param agentID AgentID (Bech32 for WasmVM | Hex for EVM | '000000@Bech32' Addresses require urlencode) + @param agentID AgentID (Bech32 for WasmVM | Hex for EVM) @return ApiAccountsGetAccountBalanceRequest */ func (a *CorecontractsApiService) AccountsGetAccountBalance(ctx context.Context, chainID string, agentID string) ApiAccountsGetAccountBalanceRequest { @@ -206,20 +206,6 @@ func (a *CorecontractsApiService) AccountsGetAccountFoundriesExecute(r ApiAccoun if localVarHTTPHeaderAccept != "" { localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept } - if r.ctx != nil { - // API Key Authentication - if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { - if apiKey, ok := auth["Authorization"]; ok { - var key string - if apiKey.Prefix != "" { - key = apiKey.Prefix + " " + apiKey.Key - } else { - key = apiKey.Key - } - localVarHeaderParams["Authorization"] = key - } - } - } req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) if err != nil { return localVarReturnValue, nil, err @@ -283,7 +269,7 @@ AccountsGetAccountNFTIDs Get all NFT ids belonging to an account @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). @param chainID ChainID (Bech32) - @param agentID AgentID (Bech32 for WasmVM | Hex for EVM | '000000@Bech32' Addresses require urlencode) + @param agentID AgentID (Bech32 for WasmVM | Hex for EVM) @return ApiAccountsGetAccountNFTIDsRequest */ func (a *CorecontractsApiService) AccountsGetAccountNFTIDs(ctx context.Context, chainID string, agentID string) ApiAccountsGetAccountNFTIDsRequest { @@ -398,7 +384,7 @@ AccountsGetAccountNonce Get the current nonce of an account @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). @param chainID ChainID (Bech32) - @param agentID AgentID (Bech32 for WasmVM | Hex for EVM | '000000@Bech32' Addresses require urlencode) + @param agentID AgentID (Bech32 for WasmVM | Hex for EVM) @return ApiAccountsGetAccountNonceRequest */ func (a *CorecontractsApiService) AccountsGetAccountNonce(ctx context.Context, chainID string, agentID string) ApiAccountsGetAccountNonceRequest { diff --git a/clients/apiclient/api_default.go b/clients/apiclient/api_default.go new file mode 100644 index 0000000000..8394b91f33 --- /dev/null +++ b/clients/apiclient/api_default.go @@ -0,0 +1,109 @@ +/* +Wasp API + +REST API for the Wasp node + +API version: 0 +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package apiclient + +import ( + "bytes" + "context" + "io/ioutil" + "net/http" + "net/url" +) + + +// DefaultApiService DefaultApi service +type DefaultApiService service + +type ApiWsGetRequest struct { + ctx context.Context + ApiService *DefaultApiService +} + +func (r ApiWsGetRequest) Execute() (*http.Response, error) { + return r.ApiService.WsGetExecute(r) +} + +/* +WsGet Method for WsGet + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @return ApiWsGetRequest +*/ +func (a *DefaultApiService) WsGet(ctx context.Context) ApiWsGetRequest { + return ApiWsGetRequest{ + ApiService: a, + ctx: ctx, + } +} + +// Execute executes the request +func (a *DefaultApiService) WsGetExecute(r ApiWsGetRequest) (*http.Response, error) { + var ( + localVarHTTPMethod = http.MethodGet + localVarPostBody interface{} + formFiles []formFile + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "DefaultApiService.WsGet") + if err != nil { + return nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/ws" + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarHTTPResponse, err + } + + localVarBody, err := ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + return localVarHTTPResponse, newErr + } + + return localVarHTTPResponse, nil +} diff --git a/clients/apiclient/client.go b/clients/apiclient/client.go index e716d4aaab..4719b768b3 100644 --- a/clients/apiclient/client.go +++ b/clients/apiclient/client.go @@ -56,6 +56,8 @@ type APIClient struct { CorecontractsApi *CorecontractsApiService + DefaultApi *DefaultApiService + MetricsApi *MetricsApiService NodeApi *NodeApiService @@ -84,6 +86,7 @@ func NewAPIClient(cfg *Configuration) *APIClient { c.AuthApi = (*AuthApiService)(&c.common) c.ChainsApi = (*ChainsApiService)(&c.common) c.CorecontractsApi = (*CorecontractsApiService)(&c.common) + c.DefaultApi = (*DefaultApiService)(&c.common) c.MetricsApi = (*MetricsApiService)(&c.common) c.NodeApi = (*NodeApiService)(&c.common) c.RequestsApi = (*RequestsApiService)(&c.common) diff --git a/clients/apiclient/docs/ChainsApi.md b/clients/apiclient/docs/ChainsApi.md index c64d3088a6..0da1af82d2 100644 --- a/clients/apiclient/docs/ChainsApi.md +++ b/clients/apiclient/docs/ChainsApi.md @@ -6,7 +6,6 @@ Method | HTTP request | Description ------------- | ------------- | ------------- [**ActivateChain**](ChainsApi.md#ActivateChain) | **Post** /chains/{chainID}/activate | Activate a chain [**AddAccessNode**](ChainsApi.md#AddAccessNode) | **Put** /chains/{chainID}/access-node/{peer} | Configure a trusted node to be an access node. -[**AttachToWebsocket**](ChainsApi.md#AttachToWebsocket) | **Get** /chains/{chainID}/ws | [**ChainsChainIDEvmGet**](ChainsApi.md#ChainsChainIDEvmGet) | **Get** /chains/{chainID}/evm | [**DeactivateChain**](ChainsApi.md#DeactivateChain) | **Post** /chains/{chainID}/deactivate | Deactivate a chain [**GetChainInfo**](ChainsApi.md#GetChainInfo) | **Get** /chains/{chainID} | Get information about a specific chain @@ -155,72 +154,6 @@ Name | Type | Description | Notes [[Back to README]](../README.md) -## AttachToWebsocket - -> AttachToWebsocket(ctx, chainID).Execute() - - - -### Example - -```go -package main - -import ( - "context" - "fmt" - "os" - openapiclient "./openapi" -) - -func main() { - chainID := "chainID_example" // string | ChainID (Bech32) - - configuration := openapiclient.NewConfiguration() - apiClient := openapiclient.NewAPIClient(configuration) - resp, r, err := apiClient.ChainsApi.AttachToWebsocket(context.Background(), chainID).Execute() - if err != nil { - fmt.Fprintf(os.Stderr, "Error when calling `ChainsApi.AttachToWebsocket``: %v\n", err) - fmt.Fprintf(os.Stderr, "Full HTTP response: %v\n", r) - } -} -``` - -### Path Parameters - - -Name | Type | Description | Notes -------------- | ------------- | ------------- | ------------- -**ctx** | **context.Context** | context for authentication, logging, cancellation, deadlines, tracing, etc. -**chainID** | **string** | ChainID (Bech32) | - -### Other Parameters - -Other parameters are passed through a pointer to a apiAttachToWebsocketRequest struct via the builder pattern - - -Name | Type | Description | Notes -------------- | ------------- | ------------- | ------------- - - -### Return type - - (empty response body) - -### Authorization - -No authorization required - -### HTTP request headers - -- **Content-Type**: Not defined -- **Accept**: Not defined - -[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) -[[Back to Model list]](../README.md#documentation-for-models) -[[Back to README]](../README.md) - - ## ChainsChainIDEvmGet > string ChainsChainIDEvmGet(ctx, chainID).Execute() @@ -709,7 +642,7 @@ import ( func main() { chainID := "chainID_example" // string | ChainID (Bech32) - stateKey := "stateKey_example" // string | Key (Hex) + stateKey := "stateKey_example" // string | State Key (Hex) configuration := openapiclient.NewConfiguration() apiClient := openapiclient.NewAPIClient(configuration) @@ -730,7 +663,7 @@ Name | Type | Description | Notes ------------- | ------------- | ------------- | ------------- **ctx** | **context.Context** | context for authentication, logging, cancellation, deadlines, tracing, etc. **chainID** | **string** | ChainID (Bech32) | -**stateKey** | **string** | Key (Hex) | +**stateKey** | **string** | State Key (Hex) | ### Other Parameters diff --git a/clients/apiclient/docs/CorecontractsApi.md b/clients/apiclient/docs/CorecontractsApi.md index 66b4e2a9ef..6323ce6983 100644 --- a/clients/apiclient/docs/CorecontractsApi.md +++ b/clients/apiclient/docs/CorecontractsApi.md @@ -56,7 +56,7 @@ import ( func main() { chainID := "chainID_example" // string | ChainID (Bech32) - agentID := "agentID_example" // string | AgentID (Bech32 for WasmVM | Hex for EVM | '000000@Bech32' Addresses require urlencode) + agentID := "agentID_example" // string | AgentID (Bech32 for WasmVM | Hex for EVM) configuration := openapiclient.NewConfiguration() apiClient := openapiclient.NewAPIClient(configuration) @@ -77,7 +77,7 @@ Name | Type | Description | Notes ------------- | ------------- | ------------- | ------------- **ctx** | **context.Context** | context for authentication, logging, cancellation, deadlines, tracing, etc. **chainID** | **string** | ChainID (Bech32) | -**agentID** | **string** | AgentID (Bech32 for WasmVM | Hex for EVM | '000000@Bech32' Addresses require urlencode) | +**agentID** | **string** | AgentID (Bech32 for WasmVM | Hex for EVM) | ### Other Parameters @@ -166,7 +166,7 @@ Name | Type | Description | Notes ### Authorization -[Authorization](../README.md#Authorization) +No authorization required ### HTTP request headers @@ -198,7 +198,7 @@ import ( func main() { chainID := "chainID_example" // string | ChainID (Bech32) - agentID := "agentID_example" // string | AgentID (Bech32 for WasmVM | Hex for EVM | '000000@Bech32' Addresses require urlencode) + agentID := "agentID_example" // string | AgentID (Bech32 for WasmVM | Hex for EVM) configuration := openapiclient.NewConfiguration() apiClient := openapiclient.NewAPIClient(configuration) @@ -219,7 +219,7 @@ Name | Type | Description | Notes ------------- | ------------- | ------------- | ------------- **ctx** | **context.Context** | context for authentication, logging, cancellation, deadlines, tracing, etc. **chainID** | **string** | ChainID (Bech32) | -**agentID** | **string** | AgentID (Bech32 for WasmVM | Hex for EVM | '000000@Bech32' Addresses require urlencode) | +**agentID** | **string** | AgentID (Bech32 for WasmVM | Hex for EVM) | ### Other Parameters @@ -269,7 +269,7 @@ import ( func main() { chainID := "chainID_example" // string | ChainID (Bech32) - agentID := "agentID_example" // string | AgentID (Bech32 for WasmVM | Hex for EVM | '000000@Bech32' Addresses require urlencode) + agentID := "agentID_example" // string | AgentID (Bech32 for WasmVM | Hex for EVM) configuration := openapiclient.NewConfiguration() apiClient := openapiclient.NewAPIClient(configuration) @@ -290,7 +290,7 @@ Name | Type | Description | Notes ------------- | ------------- | ------------- | ------------- **ctx** | **context.Context** | context for authentication, logging, cancellation, deadlines, tracing, etc. **chainID** | **string** | ChainID (Bech32) | -**agentID** | **string** | AgentID (Bech32 for WasmVM | Hex for EVM | '000000@Bech32' Addresses require urlencode) | +**agentID** | **string** | AgentID (Bech32 for WasmVM | Hex for EVM) | ### Other Parameters diff --git a/clients/apiclient/docs/DefaultApi.md b/clients/apiclient/docs/DefaultApi.md new file mode 100644 index 0000000000..dd0f2b67ff --- /dev/null +++ b/clients/apiclient/docs/DefaultApi.md @@ -0,0 +1,66 @@ +# \DefaultApi + +All URIs are relative to *http://localhost* + +Method | HTTP request | Description +------------- | ------------- | ------------- +[**WsGet**](DefaultApi.md#WsGet) | **Get** /ws | + + + +## WsGet + +> WsGet(ctx).Execute() + + + +### Example + +```go +package main + +import ( + "context" + "fmt" + "os" + openapiclient "./openapi" +) + +func main() { + + configuration := openapiclient.NewConfiguration() + apiClient := openapiclient.NewAPIClient(configuration) + resp, r, err := apiClient.DefaultApi.WsGet(context.Background()).Execute() + if err != nil { + fmt.Fprintf(os.Stderr, "Error when calling `DefaultApi.WsGet``: %v\n", err) + fmt.Fprintf(os.Stderr, "Full HTTP response: %v\n", r) + } +} +``` + +### Path Parameters + +This endpoint does not need any parameter. + +### Other Parameters + +Other parameters are passed through a pointer to a apiWsGetRequest struct via the builder pattern + + +### Return type + + (empty response body) + +### Authorization + +No authorization required + +### HTTP request headers + +- **Content-Type**: Not defined +- **Accept**: Not defined + +[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) +[[Back to Model list]](../README.md#documentation-for-models) +[[Back to README]](../README.md) + diff --git a/clients/apiclient/docs/GasFeePolicy.md b/clients/apiclient/docs/GasFeePolicy.md index b9a62e55df..d070a211c0 100644 --- a/clients/apiclient/docs/GasFeePolicy.md +++ b/clients/apiclient/docs/GasFeePolicy.md @@ -4,15 +4,16 @@ Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- +**EvmGasRatio** | [**Ratio32**](Ratio32.md) | | **GasFeeTokenId** | **string** | The gas fee token id. Empty if base token. | -**GasPerToken** | **string** | The amount of gas per token. (uint64 as string) | +**GasPerToken** | [**Ratio32**](Ratio32.md) | | **ValidatorFeeShare** | **int32** | The validator fee share. | ## Methods ### NewGasFeePolicy -`func NewGasFeePolicy(gasFeeTokenId string, gasPerToken string, validatorFeeShare int32, ) *GasFeePolicy` +`func NewGasFeePolicy(evmGasRatio Ratio32, gasFeeTokenId string, gasPerToken Ratio32, validatorFeeShare int32, ) *GasFeePolicy` NewGasFeePolicy instantiates a new GasFeePolicy object This constructor will assign default values to properties that have it defined, @@ -27,6 +28,26 @@ NewGasFeePolicyWithDefaults instantiates a new GasFeePolicy object This constructor will only assign default values to properties that have it defined, but it doesn't guarantee that properties required by API are set +### GetEvmGasRatio + +`func (o *GasFeePolicy) GetEvmGasRatio() Ratio32` + +GetEvmGasRatio returns the EvmGasRatio field if non-nil, zero value otherwise. + +### GetEvmGasRatioOk + +`func (o *GasFeePolicy) GetEvmGasRatioOk() (*Ratio32, bool)` + +GetEvmGasRatioOk returns a tuple with the EvmGasRatio field if it's non-nil, zero value otherwise +and a boolean to check if the value has been set. + +### SetEvmGasRatio + +`func (o *GasFeePolicy) SetEvmGasRatio(v Ratio32)` + +SetEvmGasRatio sets EvmGasRatio field to given value. + + ### GetGasFeeTokenId `func (o *GasFeePolicy) GetGasFeeTokenId() string` @@ -49,20 +70,20 @@ SetGasFeeTokenId sets GasFeeTokenId field to given value. ### GetGasPerToken -`func (o *GasFeePolicy) GetGasPerToken() string` +`func (o *GasFeePolicy) GetGasPerToken() Ratio32` GetGasPerToken returns the GasPerToken field if non-nil, zero value otherwise. ### GetGasPerTokenOk -`func (o *GasFeePolicy) GetGasPerTokenOk() (*string, bool)` +`func (o *GasFeePolicy) GetGasPerTokenOk() (*Ratio32, bool)` GetGasPerTokenOk returns a tuple with the GasPerToken field if it's non-nil, zero value otherwise and a boolean to check if the value has been set. ### SetGasPerToken -`func (o *GasFeePolicy) SetGasPerToken(v string)` +`func (o *GasFeePolicy) SetGasPerToken(v Ratio32)` SetGasPerToken sets GasPerToken field to given value. diff --git a/clients/apiclient/docs/Ratio32.md b/clients/apiclient/docs/Ratio32.md new file mode 100644 index 0000000000..134db3bc7c --- /dev/null +++ b/clients/apiclient/docs/Ratio32.md @@ -0,0 +1,72 @@ +# Ratio32 + +## Properties + +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**A** | **uint32** | | +**B** | **uint32** | | + +## Methods + +### NewRatio32 + +`func NewRatio32(a uint32, b uint32, ) *Ratio32` + +NewRatio32 instantiates a new Ratio32 object +This constructor will assign default values to properties that have it defined, +and makes sure properties required by API are set, but the set of arguments +will change when the set of required properties is changed + +### NewRatio32WithDefaults + +`func NewRatio32WithDefaults() *Ratio32` + +NewRatio32WithDefaults instantiates a new Ratio32 object +This constructor will only assign default values to properties that have it defined, +but it doesn't guarantee that properties required by API are set + +### GetA + +`func (o *Ratio32) GetA() uint32` + +GetA returns the A field if non-nil, zero value otherwise. + +### GetAOk + +`func (o *Ratio32) GetAOk() (*uint32, bool)` + +GetAOk returns a tuple with the A field if it's non-nil, zero value otherwise +and a boolean to check if the value has been set. + +### SetA + +`func (o *Ratio32) SetA(v uint32)` + +SetA sets A field to given value. + + +### GetB + +`func (o *Ratio32) GetB() uint32` + +GetB returns the B field if non-nil, zero value otherwise. + +### GetBOk + +`func (o *Ratio32) GetBOk() (*uint32, bool)` + +GetBOk returns a tuple with the B field if it's non-nil, zero value otherwise +and a boolean to check if the value has been set. + +### SetB + +`func (o *Ratio32) SetB(v uint32)` + +SetB sets B field to given value. + + + +[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) + + diff --git a/clients/apiclient/model_gas_fee_policy.go b/clients/apiclient/model_gas_fee_policy.go index f283cb9553..8e12370420 100644 --- a/clients/apiclient/model_gas_fee_policy.go +++ b/clients/apiclient/model_gas_fee_policy.go @@ -19,10 +19,10 @@ var _ MappedNullable = &GasFeePolicy{} // GasFeePolicy struct for GasFeePolicy type GasFeePolicy struct { + EvmGasRatio Ratio32 `json:"evmGasRatio"` // The gas fee token id. Empty if base token. GasFeeTokenId string `json:"gasFeeTokenId"` - // The amount of gas per token. (uint64 as string) - GasPerToken string `json:"gasPerToken"` + GasPerToken Ratio32 `json:"gasPerToken"` // The validator fee share. ValidatorFeeShare int32 `json:"validatorFeeShare"` } @@ -31,8 +31,9 @@ type GasFeePolicy struct { // This constructor will assign default values to properties that have it defined, // and makes sure properties required by API are set, but the set of arguments // will change when the set of required properties is changed -func NewGasFeePolicy(gasFeeTokenId string, gasPerToken string, validatorFeeShare int32) *GasFeePolicy { +func NewGasFeePolicy(evmGasRatio Ratio32, gasFeeTokenId string, gasPerToken Ratio32, validatorFeeShare int32) *GasFeePolicy { this := GasFeePolicy{} + this.EvmGasRatio = evmGasRatio this.GasFeeTokenId = gasFeeTokenId this.GasPerToken = gasPerToken this.ValidatorFeeShare = validatorFeeShare @@ -47,6 +48,30 @@ func NewGasFeePolicyWithDefaults() *GasFeePolicy { return &this } +// GetEvmGasRatio returns the EvmGasRatio field value +func (o *GasFeePolicy) GetEvmGasRatio() Ratio32 { + if o == nil { + var ret Ratio32 + return ret + } + + return o.EvmGasRatio +} + +// GetEvmGasRatioOk returns a tuple with the EvmGasRatio field value +// and a boolean to check if the value has been set. +func (o *GasFeePolicy) GetEvmGasRatioOk() (*Ratio32, bool) { + if o == nil { + return nil, false + } + return &o.EvmGasRatio, true +} + +// SetEvmGasRatio sets field value +func (o *GasFeePolicy) SetEvmGasRatio(v Ratio32) { + o.EvmGasRatio = v +} + // GetGasFeeTokenId returns the GasFeeTokenId field value func (o *GasFeePolicy) GetGasFeeTokenId() string { if o == nil { @@ -72,9 +97,9 @@ func (o *GasFeePolicy) SetGasFeeTokenId(v string) { } // GetGasPerToken returns the GasPerToken field value -func (o *GasFeePolicy) GetGasPerToken() string { +func (o *GasFeePolicy) GetGasPerToken() Ratio32 { if o == nil { - var ret string + var ret Ratio32 return ret } @@ -83,7 +108,7 @@ func (o *GasFeePolicy) GetGasPerToken() string { // GetGasPerTokenOk returns a tuple with the GasPerToken field value // and a boolean to check if the value has been set. -func (o *GasFeePolicy) GetGasPerTokenOk() (*string, bool) { +func (o *GasFeePolicy) GetGasPerTokenOk() (*Ratio32, bool) { if o == nil { return nil, false } @@ -91,7 +116,7 @@ func (o *GasFeePolicy) GetGasPerTokenOk() (*string, bool) { } // SetGasPerToken sets field value -func (o *GasFeePolicy) SetGasPerToken(v string) { +func (o *GasFeePolicy) SetGasPerToken(v Ratio32) { o.GasPerToken = v } @@ -129,6 +154,7 @@ func (o GasFeePolicy) MarshalJSON() ([]byte, error) { func (o GasFeePolicy) ToMap() (map[string]interface{}, error) { toSerialize := map[string]interface{}{} + toSerialize["evmGasRatio"] = o.EvmGasRatio toSerialize["gasFeeTokenId"] = o.GasFeeTokenId toSerialize["gasPerToken"] = o.GasPerToken toSerialize["validatorFeeShare"] = o.ValidatorFeeShare diff --git a/clients/apiclient/model_ratio32.go b/clients/apiclient/model_ratio32.go new file mode 100644 index 0000000000..279bd47d90 --- /dev/null +++ b/clients/apiclient/model_ratio32.go @@ -0,0 +1,144 @@ +/* +Wasp API + +REST API for the Wasp node + +API version: 0 +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package apiclient + +import ( + "encoding/json" +) + +// checks if the Ratio32 type satisfies the MappedNullable interface at compile time +var _ MappedNullable = &Ratio32{} + +// Ratio32 struct for Ratio32 +type Ratio32 struct { + A uint32 `json:"a"` + B uint32 `json:"b"` +} + +// NewRatio32 instantiates a new Ratio32 object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewRatio32(a uint32, b uint32) *Ratio32 { + this := Ratio32{} + this.A = a + this.B = b + return &this +} + +// NewRatio32WithDefaults instantiates a new Ratio32 object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewRatio32WithDefaults() *Ratio32 { + this := Ratio32{} + return &this +} + +// GetA returns the A field value +func (o *Ratio32) GetA() uint32 { + if o == nil { + var ret uint32 + return ret + } + + return o.A +} + +// GetAOk returns a tuple with the A field value +// and a boolean to check if the value has been set. +func (o *Ratio32) GetAOk() (*uint32, bool) { + if o == nil { + return nil, false + } + return &o.A, true +} + +// SetA sets field value +func (o *Ratio32) SetA(v uint32) { + o.A = v +} + +// GetB returns the B field value +func (o *Ratio32) GetB() uint32 { + if o == nil { + var ret uint32 + return ret + } + + return o.B +} + +// GetBOk returns a tuple with the B field value +// and a boolean to check if the value has been set. +func (o *Ratio32) GetBOk() (*uint32, bool) { + if o == nil { + return nil, false + } + return &o.B, true +} + +// SetB sets field value +func (o *Ratio32) SetB(v uint32) { + o.B = v +} + +func (o Ratio32) MarshalJSON() ([]byte, error) { + toSerialize,err := o.ToMap() + if err != nil { + return []byte{}, err + } + return json.Marshal(toSerialize) +} + +func (o Ratio32) ToMap() (map[string]interface{}, error) { + toSerialize := map[string]interface{}{} + toSerialize["a"] = o.A + toSerialize["b"] = o.B + return toSerialize, nil +} + +type NullableRatio32 struct { + value *Ratio32 + isSet bool +} + +func (v NullableRatio32) Get() *Ratio32 { + return v.value +} + +func (v *NullableRatio32) Set(val *Ratio32) { + v.value = val + v.isSet = true +} + +func (v NullableRatio32) IsSet() bool { + return v.isSet +} + +func (v *NullableRatio32) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableRatio32(val *Ratio32) *NullableRatio32 { + return &NullableRatio32{value: val, isSet: true} +} + +func (v NullableRatio32) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableRatio32) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/contracts/wasm/corecontracts/test/core_governance_test.go b/contracts/wasm/corecontracts/test/core_governance_test.go index 07d904c8af..ce38096ff1 100644 --- a/contracts/wasm/corecontracts/test/core_governance_test.go +++ b/contracts/wasm/corecontracts/test/core_governance_test.go @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/require" "github.com/iotaledger/wasp/packages/isc" + "github.com/iotaledger/wasp/packages/util" "github.com/iotaledger/wasp/packages/vm/core/governance" "github.com/iotaledger/wasp/packages/vm/gas" "github.com/iotaledger/wasp/packages/wasmvm/wasmlib/go/wasmlib/coregovernance" @@ -95,7 +96,7 @@ func TestSetFeePolicy(t *testing.T) { require.NoError(t, ctx.Err) gfp0 := gas.DefaultGasFeePolicy() - gfp0.GasPerToken = 10 + gfp0.GasPerToken = util.Ratio32{A: 1, B: 10} f := coregovernance.ScFuncs.SetFeePolicy(ctx) f.Params.FeePolicyBytes().SetValue(gfp0.Bytes()) f.Func.Post() @@ -171,8 +172,8 @@ func TestGetFeePolicy(t *testing.T) { gfp, err := gas.FeePolicyFromBytes(fpBin) require.NoError(t, err) require.True(t, isc.IsEmptyNativeTokenID(gfp.GasFeeTokenID)) // default fee token ID is empty - require.Equal(t, uint64(100), gfp.GasPerToken) // default gas fee is 100 - require.Equal(t, uint8(0), gfp.ValidatorFeeShare) // default fee share is 0 + require.Equal(t, gas.DefaultGasPerToken, gfp.GasPerToken) + require.Equal(t, uint8(0), gfp.ValidatorFeeShare) // default fee share is 0 } func TestGetChainInfo(t *testing.T) { diff --git a/documentation/docs/guide/core_concepts/core_contracts/governance.md b/documentation/docs/guide/core_concepts/core_contracts/governance.md index 558e12032d..bddac87e84 100644 --- a/documentation/docs/guide/core_concepts/core_contracts/governance.md +++ b/documentation/docs/guide/core_concepts/core_contracts/governance.md @@ -44,7 +44,7 @@ The Fee Policy looks like the following: { TokenID []byte // id of the token used to pay for gas (nil if the base token should be used (iota/shimmer)) - GasPerToken uint64 // how many gas units are paid for each token + GasPerToken Ratio32 // how many gas units are paid for each token ValidatorFeeShare uint8 // percentage of the fees that are credited to the validators (0 - 100) } @@ -187,7 +187,7 @@ Changes the ISC : EVM gas ratio. #### Parameters -- `e` ([`GasRatio`](#evm-gas-ratio)): The ISC : EVM gas ratio. +- `e` ([`Ratio32`](#ratio32)): The ISC : EVM gas ratio. --- @@ -237,7 +237,7 @@ Returns the ISC : EVM gas ratio. #### Returns -- `e` ([`GasRatio`](#evm-gas-ratio)): The ISC : EVM gas ratio. +- `e` ([`Ratio32`](#ratio32)): The ISC : EVM gas ratio. ### `getChainNodes()` @@ -259,11 +259,11 @@ Returns whether the chain is ongoing maintenance. ## Schemas -### `EVM gas ratio` +### `Ratio32` -ISC : EVM gas ratio is expressed as an `a : b` ratio, where ` = * / `. +A ratio between two values `x` and `y`, expressed as two `int32` numbers `a:b`, where `y = x * b/a`. -`GasRatio` is encoded as the concatenation of the two `uint32` values `a` & `b`. +`Ratio32` is encoded as the concatenation of the two `uint32` values `a` & `b`. ### `FeePolicy` @@ -272,10 +272,10 @@ ISC : EVM gas ratio is expressed as an `a : b` ratio, where ` = math.MaxUint32 { + log.Warn("m001GasPerTokenToRatio32: trimming gas per token") + fpOld.GasPerToken = math.MaxUint32 + } + return &gas.GasFeePolicy{ + GasFeeTokenID: fpOld.GasFeeTokenID, + GasFeeTokenDecimals: fpOld.GasFeeTokenDecimals, + GasPerToken: util.Ratio32{A: 1, B: uint32(fpOld.GasPerToken)}, + EVMGasRatio: fpOld.EVMGasRatio, + ValidatorFeeShare: fpOld.ValidatorFeeShare, + }, nil +} + +type gasFeePolicyOld struct { + GasFeeTokenID iotago.NativeTokenID + GasFeeTokenDecimals uint32 + GasPerToken uint64 + EVMGasRatio util.Ratio32 + ValidatorFeeShare uint8 +} + +func feePolicyFromBytesOld(data []byte) (*gasFeePolicyOld, error) { + ret := &gasFeePolicyOld{} + mu := marshalutil.New(data) + var gasNativeToken bool + var err error + if gasNativeToken, err = mu.ReadBool(); err != nil { + return nil, err + } + if gasNativeToken { + b, err2 := mu.ReadBytes(iotago.NativeTokenIDLength) + if err2 != nil { + return nil, err2 + } + ret.GasFeeTokenID = iotago.NativeTokenID{} + copy(ret.GasFeeTokenID[:], b) + if ret.GasFeeTokenDecimals, err2 = mu.ReadUint32(); err2 != nil { + return nil, err2 + } + } + if ret.GasPerToken, err = mu.ReadUint64(); err != nil { + return nil, err + } + if ret.ValidatorFeeShare, err = mu.ReadUint8(); err != nil { + return nil, err + } + if ret.EVMGasRatio, err = gas.ReadRatio32(mu); err != nil { + return nil, err + } + return ret, nil +} diff --git a/packages/vm/core/migrations/m001_gaspertoken_to_ratio32_test.go b/packages/vm/core/migrations/m001_gaspertoken_to_ratio32_test.go new file mode 100644 index 0000000000..956ac85026 --- /dev/null +++ b/packages/vm/core/migrations/m001_gaspertoken_to_ratio32_test.go @@ -0,0 +1,16 @@ +package migrations + +import ( + "encoding/hex" + "testing" + + "github.com/stretchr/testify/require" +) + +func TestM001GasPerTokenToRatio32(t *testing.T) { + oldFeePolicyBin, err := hex.DecodeString("006400000000000000000100000001000000") + require.NoError(t, err) + fp, err := m001ConvertFeePolicy(oldFeePolicyBin) + require.NoError(t, err) + t.Log(fp) +} diff --git a/packages/vm/core/migrations/migrations.go b/packages/vm/core/migrations/migrations.go new file mode 100644 index 0000000000..30a9f1e3ed --- /dev/null +++ b/packages/vm/core/migrations/migrations.go @@ -0,0 +1,25 @@ +package migrations + +import ( + "github.com/iotaledger/hive.go/core/logger" + "github.com/iotaledger/wasp/packages/isc/coreutil" + "github.com/iotaledger/wasp/packages/kv" +) + +const BaseSchemaVersion = uint32(0) + +type Migration struct { + Contract *coreutil.ContractInfo + Apply func(state kv.KVStore, log *logger.Logger) error +} + +// Add new migrations to the end of this list, and they will be applied before +// creating the next block. +// The first migration on the list is applied when schema version = +// BaseSchemaVersion, and after applying each migration the schema version is +// incremented. +// Old migrations can be pruned; for each migration pruned increment +// BaseSchemaVersion by one. +var Migrations = []Migration{ + m001GasPerTokenToRatio32, +} diff --git a/packages/vm/core/root/interface.go b/packages/vm/core/root/interface.go index 494f9f1fc5..b1aef6eaef 100644 --- a/packages/vm/core/root/interface.go +++ b/packages/vm/core/root/interface.go @@ -10,6 +10,8 @@ var Contract = coreutil.NewContract(coreutil.CoreContractRoot, "Root Contract") // state variables const ( + StateVarSchemaVersion = "v" + StateVarContractRegistry = "r" StateVarDeployPermissionsEnabled = "a" StateVarDeployPermissions = "p" diff --git a/packages/vm/core/root/migrations.go b/packages/vm/core/root/migrations.go new file mode 100644 index 0000000000..b1a6e7354c --- /dev/null +++ b/packages/vm/core/root/migrations.go @@ -0,0 +1,14 @@ +package root + +import ( + "github.com/iotaledger/wasp/packages/kv" + "github.com/iotaledger/wasp/packages/kv/codec" +) + +func SetSchemaVersion(state kv.KVStore, v uint32) { + state.Set(StateVarSchemaVersion, codec.EncodeUint32(v)) +} + +func GetSchemaVersion(state kv.KVStoreReader) uint32 { + return codec.MustDecodeUint32(state.MustGet(StateVarSchemaVersion), 0) +} diff --git a/packages/vm/gas/policy.go b/packages/vm/gas/policy.go index 913d80d9f7..3ebb3ca35c 100644 --- a/packages/vm/gas/policy.go +++ b/packages/vm/gas/policy.go @@ -3,14 +3,18 @@ package gas import ( "errors" "fmt" - "math" "github.com/iotaledger/hive.go/core/marshalutil" iotago "github.com/iotaledger/iota.go/v3" "github.com/iotaledger/wasp/packages/util" ) -var emptyNativeTokenID = iotago.NativeTokenID{} +var ( + emptyNativeTokenID = iotago.NativeTokenID{} + + // By default each token pays for 100 units of gas + DefaultGasPerToken = util.Ratio32{A: 1, B: 100} +) type GasFeePolicy struct { // GasFeeTokenID contains iotago.NativeTokenID used to pay for gas, or nil if base token are used for gas fee @@ -18,11 +22,11 @@ type GasFeePolicy struct { // GasFeeTokenDecimals the number of decimals in the native token used to pay for gas fees. Only considered if GasFeeTokenID != nil GasFeeTokenDecimals uint32 - // GasPerToken specifies how many gas units are paid for each token ( 100 means 1 tokens pays for 100 gas) - GasPerToken uint64 + // GasPerToken specifies how many gas units are paid for each token. + GasPerToken util.Ratio32 // X = fee, Y = gas => fee = gas * A/B - // EVMGasRatio expresses the ratio at which EVM gas is converted to ISC gas (evm gas used * A/B) - EVMGasRatio util.Ratio32 + // EVMGasRatio expresses the ratio at which EVM gas is converted to ISC gas + EVMGasRatio util.Ratio32 // X = ISC gas, Y = EVM gas => ISC gas = EVM gas * A/B // ValidatorFeeShare Validator/Governor fee split: percentage of fees which goes to Validator // 0 mean all goes to Governor @@ -30,16 +34,22 @@ type GasFeePolicy struct { ValidatorFeeShare uint8 } -func calcFee(gasUnits, gasPerToken uint64) uint64 { - return uint64(math.Ceil(float64(gasUnits) / float64(gasPerToken))) +// FeeFromGas calculates fee = gas * A/B +func FeeFromGas(gasUnits uint64, gasPerToken util.Ratio32) uint64 { + return gasPerToken.XCeil64(gasUnits) } -// FeeFromGas return ownerFee and validatorFee -func (p *GasFeePolicy) FeeFromGas(gasUnits, availableTokens uint64) (sendToOwner, sendToValidator uint64) { +func (p *GasFeePolicy) FeeFromGas(gasUnits uint64) uint64 { + return FeeFromGas(gasUnits, p.GasPerToken) +} + +// FeeFromGasBurned calculates the how many tokens to take and where +// to deposit them. +func (p *GasFeePolicy) FeeFromGasBurned(gasUnits, availableTokens uint64) (sendToOwner, sendToValidator uint64) { var fee uint64 // round up - fee = calcFee(gasUnits, p.GasPerToken) + fee = p.FeeFromGas(gasUnits) fee = util.MinUint64(fee, availableTokens) validatorPercentage := p.ValidatorFeeShare @@ -56,22 +66,22 @@ func (p *GasFeePolicy) FeeFromGas(gasUnits, availableTokens uint64) (sendToOwner } func (p *GasFeePolicy) MinFee() uint64 { - return calcFee(BurnCodeMinimumGasPerRequest1P.Cost(), p.GasPerToken) + return p.FeeFromGas(BurnCodeMinimumGasPerRequest1P.Cost()) } func (p *GasFeePolicy) IsEnoughForMinimumFee(availableTokens uint64) bool { return availableTokens >= p.MinFee() } -func (p *GasFeePolicy) AffordableGasBudgetFromAvailableTokens(availableTokens uint64) uint64 { - return availableTokens * p.GasPerToken +func (p *GasFeePolicy) GasBudgetFromTokens(availableTokens uint64) uint64 { + return p.GasPerToken.YFloor64(availableTokens) } func DefaultGasFeePolicy() *GasFeePolicy { return &GasFeePolicy{ GasFeeTokenID: iotago.NativeTokenID{}, // default is base token - GasPerToken: 100, // each token pays for 100 units of gas - ValidatorFeeShare: 0, // by default all goes to the governor + GasPerToken: DefaultGasPerToken, + ValidatorFeeShare: 0, // by default all goes to the governor EVMGasRatio: DefaultEVMGasRatio, } } @@ -84,7 +94,7 @@ func MustGasFeePolicyFromBytes(data []byte) *GasFeePolicy { return ret } -var ErrInvalidEVMGasRatio = errors.New("EVM gas ratio must have both components != 0") +var ErrInvalidRatio = errors.New("ratio must have both components != 0") func FeePolicyFromBytes(data []byte) (*GasFeePolicy, error) { ret := &GasFeePolicy{} @@ -105,17 +115,28 @@ func FeePolicyFromBytes(data []byte) (*GasFeePolicy, error) { return nil, err2 } } - if ret.GasPerToken, err = mu.ReadUint64(); err != nil { + if ret.GasPerToken, err = ReadRatio32(mu); err != nil { return nil, err } if ret.ValidatorFeeShare, err = mu.ReadUint8(); err != nil { return nil, err } - if ret.EVMGasRatio, err = util.Ratio32FromBytes(mu.ReadRemainingBytes()); err != nil { + if ret.EVMGasRatio, err = ReadRatio32(mu); err != nil { return nil, err } - if ret.EVMGasRatio.A == 0 || ret.EVMGasRatio.B == 0 { - return nil, ErrInvalidEVMGasRatio + return ret, nil +} + +func ReadRatio32(mu *marshalutil.MarshalUtil) (ret util.Ratio32, err error) { + b, err := mu.ReadBytes(8) + if err != nil { + return ret, err + } + if ret, err = util.Ratio32FromBytes(b); err != nil { + return ret, err + } + if ret.HasZeroComponent() { + return ret, ErrInvalidRatio } return ret, nil } @@ -128,7 +149,7 @@ func (p *GasFeePolicy) Bytes() []byte { mu.WriteBytes(p.GasFeeTokenID[:]) mu.WriteUint32(p.GasFeeTokenDecimals) } - mu.WriteUint64(p.GasPerToken) + mu.WriteBytes(p.GasPerToken.Bytes()) mu.WriteUint8(p.ValidatorFeeShare) mu.WriteBytes(p.EVMGasRatio.Bytes()) return mu.Bytes() @@ -138,14 +159,14 @@ func (p *GasFeePolicy) String() string { return fmt.Sprintf(` GasFeeTokenID: %s GasFeeTokenDecimals %d - GasPerToken %d + GasPerToken %s EVMGasRatio %s ValidatorFeeShare %d `, p.GasFeeTokenID, p.GasFeeTokenDecimals, p.GasPerToken, - p.EVMGasRatio.String(), + p.EVMGasRatio, p.ValidatorFeeShare, ) } diff --git a/packages/vm/gas/policy_test.go b/packages/vm/gas/policy_test.go index 939a2a6b27..6f3283a2eb 100644 --- a/packages/vm/gas/policy_test.go +++ b/packages/vm/gas/policy_test.go @@ -19,7 +19,7 @@ func TestFeePolicySerde(t *testing.T) { feePolicy = &GasFeePolicy{ GasFeeTokenID: tpkg.RandNativeToken().ID, - GasPerToken: uint64(100), + GasPerToken: DefaultGasPerToken, ValidatorFeeShare: 10, EVMGasRatio: DefaultEVMGasRatio, } diff --git a/packages/vm/vmcontext/migrations.go b/packages/vm/vmcontext/migrations.go new file mode 100644 index 0000000000..c20cd36940 --- /dev/null +++ b/packages/vm/vmcontext/migrations.go @@ -0,0 +1,48 @@ +package vmcontext + +import ( + "fmt" + + "github.com/iotaledger/wasp/packages/kv" + "github.com/iotaledger/wasp/packages/vm/core/migrations" + "github.com/iotaledger/wasp/packages/vm/core/root" +) + +func (vmctx *VMContext) runMigrations(baseSchemaVersion uint32, allMigrations []migrations.Migration) { + latestSchemaVersion := baseSchemaVersion + uint32(len(allMigrations)) + + if vmctx.task.AnchorOutput.StateIndex == 0 { + // initializing new chain -- set the schema to latest version + vmctx.callCore(root.Contract, func(s kv.KVStore) { + root.SetSchemaVersion(s, latestSchemaVersion) + }) + return + } + + var currentVersion uint32 + vmctx.callCore(root.Contract, func(s kv.KVStore) { + currentVersion = root.GetSchemaVersion(s) + }) + if currentVersion < baseSchemaVersion { + panic(fmt.Sprintf("inconsistency: node with schema version %d is behind pruned migrations (should be >= %d)", currentVersion, baseSchemaVersion)) + } + if currentVersion > latestSchemaVersion { + panic(fmt.Sprintf("inconsistency: node with schema version %d is ahead latest schema version (should be <= %d)", currentVersion, latestSchemaVersion)) + } + + for currentVersion < latestSchemaVersion { + migration := allMigrations[currentVersion-baseSchemaVersion] + + vmctx.callCore(migration.Contract, func(s kv.KVStore) { + err := migration.Apply(s, vmctx.task.Log) + if err != nil { + panic(fmt.Sprintf("failed applying migration: %s", err)) + } + }) + + currentVersion++ + vmctx.callCore(root.Contract, func(s kv.KVStore) { + root.SetSchemaVersion(s, currentVersion) + }) + } +} diff --git a/packages/vm/vmcontext/migrations_test.go b/packages/vm/vmcontext/migrations_test.go new file mode 100644 index 0000000000..aea8cc4ddf --- /dev/null +++ b/packages/vm/vmcontext/migrations_test.go @@ -0,0 +1,140 @@ +package vmcontext + +import ( + "testing" + "time" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "go.uber.org/zap" + + "github.com/iotaledger/hive.go/core/kvstore" + "github.com/iotaledger/hive.go/core/kvstore/mapdb" + iotago "github.com/iotaledger/iota.go/v3" + "github.com/iotaledger/wasp/packages/kv" + "github.com/iotaledger/wasp/packages/state" + "github.com/iotaledger/wasp/packages/vm" + "github.com/iotaledger/wasp/packages/vm/core/governance" + "github.com/iotaledger/wasp/packages/vm/core/migrations" + "github.com/iotaledger/wasp/packages/vm/core/root" +) + +type migrationsTestEnv struct { + t *testing.T + db kvstore.KVStore + cs state.Store + vmctx *VMContext + + counter int + incCounter migrations.Migration + panic migrations.Migration +} + +func (e *migrationsTestEnv) getSchemaVersion() (ret uint32) { + e.vmctx.withStateUpdate(func() { + e.vmctx.callCore(root.Contract, func(s kv.KVStore) { + ret = root.GetSchemaVersion(s) + }) + }) + return +} + +func (e *migrationsTestEnv) setSchemaVersion(v uint32) { + e.vmctx.withStateUpdate(func() { + e.vmctx.callCore(root.Contract, func(s kv.KVStore) { + root.SetSchemaVersion(s, v) + }) + }) +} + +func newMigrationsTest(t *testing.T, stateIndex uint32) *migrationsTestEnv { + db := mapdb.NewMapDB() + cs := state.InitChainStore(db) + latest, err := cs.LatestBlock() + assert.NoError(t, err) + stateDraft, err := cs.NewStateDraft(time.Now(), latest.L1Commitment()) + assert.NoError(t, err) + vmctx := &VMContext{ + task: &vm.VMTask{ + StateDraft: stateDraft, + AnchorOutput: &iotago.AliasOutput{ + StateIndex: stateIndex, + }, + }, + } + + env := &migrationsTestEnv{ + t: t, + db: db, + cs: cs, + vmctx: vmctx, + } + + env.incCounter = migrations.Migration{ + Contract: governance.Contract, + Apply: func(state kv.KVStore, log *zap.SugaredLogger) error { + env.counter++ + return nil + }, + } + + env.panic = migrations.Migration{ + Contract: governance.Contract, + Apply: func(state kv.KVStore, log *zap.SugaredLogger) error { + panic("should not be called") + }, + } + + return env +} + +func TestMigrationsStateIndex0(t *testing.T) { + env := newMigrationsTest(t, 0) + + require.EqualValues(t, 0, env.getSchemaVersion()) + + env.vmctx.withStateUpdate(func() { + env.vmctx.runMigrations(0, []migrations.Migration{env.panic, env.panic, env.panic}) + }) + + require.EqualValues(t, 3, env.getSchemaVersion()) +} + +func TestMigrationsStateIndex1(t *testing.T) { + env := newMigrationsTest(t, 1) + + require.EqualValues(t, 0, env.getSchemaVersion()) + + env.vmctx.withStateUpdate(func() { + env.vmctx.runMigrations(0, []migrations.Migration{env.incCounter, env.incCounter, env.incCounter}) + }) + + require.EqualValues(t, 3, env.counter) + require.EqualValues(t, 3, env.getSchemaVersion()) +} + +func TestMigrationsStateIndex1Current1(t *testing.T) { + env := newMigrationsTest(t, 1) + + env.setSchemaVersion(1) + + env.vmctx.withStateUpdate(func() { + env.vmctx.runMigrations(0, []migrations.Migration{env.panic, env.incCounter, env.incCounter}) + }) + + require.EqualValues(t, 2, env.counter) + require.EqualValues(t, 3, env.getSchemaVersion()) +} + +func TestMigrationsStateIndex1Current2Base1(t *testing.T) { + env := newMigrationsTest(t, 1) + + env.setSchemaVersion(2) + + env.vmctx.withStateUpdate(func() { + env.vmctx.runMigrations(1, []migrations.Migration{env.panic, env.incCounter, env.incCounter}) + }) + + require.EqualValues(t, 2, env.counter) + require.EqualValues(t, 4, env.getSchemaVersion()) +} diff --git a/packages/vm/vmcontext/runreq.go b/packages/vm/vmcontext/runreq.go index 1da24e5417..a245f5bc06 100644 --- a/packages/vm/vmcontext/runreq.go +++ b/packages/vm/vmcontext/runreq.go @@ -263,10 +263,10 @@ func (vmctx *VMContext) calculateAffordableGasBudget() uint64 { // calculate how many tokens for gas fee can be guaranteed after taking into account the allowance guaranteedFeeTokens := vmctx.calcGuaranteedFeeTokens() // calculate how many tokens maximum will be charged taking into account the budget - f1, f2 := vmctx.chainInfo.GasFeePolicy.FeeFromGas(gasBudget, guaranteedFeeTokens) + f1, f2 := vmctx.chainInfo.GasFeePolicy.FeeFromGasBurned(gasBudget, guaranteedFeeTokens) vmctx.gasMaxTokensToSpendForGasFee = f1 + f2 // calculate affordable gas budget - affordable := vmctx.chainInfo.GasFeePolicy.AffordableGasBudgetFromAvailableTokens(guaranteedFeeTokens) + affordable := vmctx.chainInfo.GasFeePolicy.GasBudgetFromTokens(guaranteedFeeTokens) // adjust gas budget to what is affordable affordable = util.MinUint64(gasBudget, affordable) // cap gas to the maximum allowed per tx @@ -345,7 +345,7 @@ func (vmctx *VMContext) chargeGasFee() { } // total fees to charge - sendToOwner, sendToValidator := vmctx.chainInfo.GasFeePolicy.FeeFromGas(vmctx.GasBurned(), availableToPayFee) + sendToOwner, sendToValidator := vmctx.chainInfo.GasFeePolicy.FeeFromGasBurned(vmctx.GasBurned(), availableToPayFee) vmctx.gasFeeCharged = sendToOwner + sendToValidator // calc gas totals diff --git a/packages/vm/vmcontext/vmcontext.go b/packages/vm/vmcontext/vmcontext.go index b7da670a81..6edfedff26 100644 --- a/packages/vm/vmcontext/vmcontext.go +++ b/packages/vm/vmcontext/vmcontext.go @@ -16,6 +16,7 @@ import ( "github.com/iotaledger/wasp/packages/vm/core/blob" "github.com/iotaledger/wasp/packages/vm/core/blocklog" "github.com/iotaledger/wasp/packages/vm/core/governance" + "github.com/iotaledger/wasp/packages/vm/core/migrations" "github.com/iotaledger/wasp/packages/vm/core/root" "github.com/iotaledger/wasp/packages/vm/execution" "github.com/iotaledger/wasp/packages/vm/gas" @@ -106,26 +107,27 @@ func CreateVMContext(task *vm.VMTask) *VMContext { } // at the beginning of each block - if task.AnchorOutput.StateIndex > 0 { - ret.currentStateUpdate = NewStateUpdate() - - // load and validate chain's storage deposit assumptions about internal outputs. They must not get bigger! - ret.callCore(accounts.Contract, func(s kv.KVStore) { - ret.storageDepositAssumptions = accounts.GetStorageDepositAssumptions(s) - }) - currentStorageDepositValues := transaction.NewStorageDepositEstimate() - if currentStorageDepositValues.AnchorOutput > ret.storageDepositAssumptions.AnchorOutput || - currentStorageDepositValues.NativeTokenOutput > ret.storageDepositAssumptions.NativeTokenOutput { - panic(vm.ErrInconsistentStorageDepositAssumptions) - } + ret.withStateUpdate(func() { + ret.runMigrations(migrations.BaseSchemaVersion, migrations.Migrations) + }) - // save the anchor tx ID of the current state - ret.callCore(blocklog.Contract, func(s kv.KVStore) { - blocklog.UpdateLatestBlockInfo(s, ret.task.AnchorOutputID.TransactionID(), l1Commitment) + if task.AnchorOutput.StateIndex > 0 { + ret.withStateUpdate(func() { + // load and validate chain's storage deposit assumptions about internal outputs. They must not get bigger! + ret.callCore(accounts.Contract, func(s kv.KVStore) { + ret.storageDepositAssumptions = accounts.GetStorageDepositAssumptions(s) + }) + currentStorageDepositValues := transaction.NewStorageDepositEstimate() + if currentStorageDepositValues.AnchorOutput > ret.storageDepositAssumptions.AnchorOutput || + currentStorageDepositValues.NativeTokenOutput > ret.storageDepositAssumptions.NativeTokenOutput { + panic(vm.ErrInconsistentStorageDepositAssumptions) + } + + // save the anchor tx ID of the current state + ret.callCore(blocklog.Contract, func(s kv.KVStore) { + blocklog.UpdateLatestBlockInfo(s, ret.task.AnchorOutputID.TransactionID(), l1Commitment) + }) }) - - ret.currentStateUpdate.Mutations.ApplyTo(task.StateDraft) - ret.currentStateUpdate = nil } else { // assuming storage deposit assumptions for the first block. It must be consistent with parameters in the init request ret.storageDepositAssumptions = transaction.NewStorageDepositEstimate() @@ -152,17 +154,25 @@ func CreateVMContext(task *vm.VMTask) *VMContext { return ret } +func (vmctx *VMContext) withStateUpdate(f func()) { + vmctx.currentStateUpdate = NewStateUpdate() + f() + vmctx.currentStateUpdate.Mutations.ApplyTo(vmctx.task.StateDraft) + vmctx.currentStateUpdate = nil +} + // CloseVMContext does the closing actions on the block // return nil for normal block and rotation address for rotation block func (vmctx *VMContext) CloseVMContext(numRequests, numSuccess, numOffLedger uint16) (uint32, *state.L1Commitment, time.Time, iotago.Address) { vmctx.GasBurnEnable(false) - vmctx.currentStateUpdate = NewStateUpdate() // need this before to make state valid - rotationAddr := vmctx.saveBlockInfo(numRequests, numSuccess, numOffLedger) - if vmctx.task.AnchorOutput.StateIndex > 0 { - vmctx.closeBlockContexts() - } - vmctx.saveInternalUTXOs() - vmctx.currentStateUpdate.Mutations.ApplyTo(vmctx.task.StateDraft) + var rotationAddr iotago.Address + vmctx.withStateUpdate(func() { + rotationAddr = vmctx.saveBlockInfo(numRequests, numSuccess, numOffLedger) + if vmctx.task.AnchorOutput.StateIndex > 0 { + vmctx.closeBlockContexts() + } + vmctx.saveInternalUTXOs() + }) block := vmctx.task.Store.ExtractBlock(vmctx.task.StateDraft) @@ -231,20 +241,19 @@ func (vmctx *VMContext) OpenBlockContexts() { panic("expected gasBurnEnabled == false") } - vmctx.currentStateUpdate = NewStateUpdate() - vmctx.loadChainConfig() + vmctx.withStateUpdate(func() { + vmctx.loadChainConfig() - var subs []root.BlockContextSubscription - vmctx.callCore(root.Contract, func(s kv.KVStore) { - subs = root.GetBlockContextSubscriptions(s) + var subs []root.BlockContextSubscription + vmctx.callCore(root.Contract, func(s kv.KVStore) { + subs = root.GetBlockContextSubscriptions(s) + }) + vmctx.callerIsVM = true + for _, sub := range subs { + vmctx.callProgram(sub.Contract, sub.OpenFunc, nil, nil) + } + vmctx.callerIsVM = false }) - vmctx.callerIsVM = true - for _, sub := range subs { - vmctx.callProgram(sub.Contract, sub.OpenFunc, nil, nil) - } - vmctx.callerIsVM = false - - vmctx.currentStateUpdate.Mutations.ApplyTo(vmctx.task.StateDraft) } // closeBlockContexts closes block contexts in deterministic FIFO sequence diff --git a/packages/webapi/controllers/corecontracts/controller.go b/packages/webapi/controllers/corecontracts/controller.go index 950a88148e..617d3dd632 100644 --- a/packages/webapi/controllers/corecontracts/controller.go +++ b/packages/webapi/controllers/corecontracts/controller.go @@ -172,7 +172,7 @@ func (c *Controller) addGovernanceContractRoutes(api echoswagger.ApiGroup, mocke api.GET("chains/:chainID/core/governance/chaininfo", c.getChainInfo). AddParamPath("", params.ParamChainID, params.DescriptionChainID). AddResponse(http.StatusUnauthorized, "Unauthorized (Wrong permissions, missing token)", authentication.ValidationError{}, nil). - AddResponse(http.StatusOK, "The chain info", mocker.Get(GovChainInfoResponse{}), nil). + AddResponse(http.StatusOK, "The chain info", mocker.Get(models.GovChainInfoResponse{}), nil). SetOperationId("governanceGetChainInfo"). SetDescription("If you are using the common API functions, you most likely rather want to use '/chains/:chainID' to get information about a chain."). SetSummary("Get the chain info") @@ -180,7 +180,7 @@ func (c *Controller) addGovernanceContractRoutes(api echoswagger.ApiGroup, mocke api.GET("chains/:chainID/core/governance/chainowner", c.getChainOwner). AddParamPath("", params.ParamChainID, params.DescriptionChainID). AddResponse(http.StatusUnauthorized, "Unauthorized (Wrong permissions, missing token)", authentication.ValidationError{}, nil). - AddResponse(http.StatusOK, "The chain owner", mocker.Get(GovChainOwnerResponse{}), nil). + AddResponse(http.StatusOK, "The chain owner", mocker.Get(models.GovChainOwnerResponse{}), nil). SetOperationId("governanceGetChainOwner"). SetDescription("Returns the chain owner"). SetSummary("Get the chain owner") @@ -188,7 +188,7 @@ func (c *Controller) addGovernanceContractRoutes(api echoswagger.ApiGroup, mocke api.GET("chains/:chainID/core/governance/allowedstatecontrollers", c.getAllowedStateControllerAddresses). AddParamPath("", params.ParamChainID, params.DescriptionChainID). AddResponse(http.StatusUnauthorized, "Unauthorized (Wrong permissions, missing token)", authentication.ValidationError{}, nil). - AddResponse(http.StatusOK, "The state controller addresses", mocker.Get(GovAllowedStateControllerAddressesResponse{}), nil). + AddResponse(http.StatusOK, "The state controller addresses", mocker.Get(models.GovAllowedStateControllerAddressesResponse{}), nil). SetOperationId("governanceGetAllowedStateControllerAddresses"). SetDescription("Returns the allowed state controller addresses"). SetSummary("Get the allowed state controller addresses") diff --git a/packages/webapi/controllers/corecontracts/governance.go b/packages/webapi/controllers/corecontracts/governance.go index 9967c98022..a1830c7497 100644 --- a/packages/webapi/controllers/corecontracts/governance.go +++ b/packages/webapi/controllers/corecontracts/governance.go @@ -5,52 +5,29 @@ import ( "github.com/labstack/echo/v4" - iotago "github.com/iotaledger/iota.go/v3" "github.com/iotaledger/wasp/packages/isc" "github.com/iotaledger/wasp/packages/parameters" "github.com/iotaledger/wasp/packages/vm/core/governance" + "github.com/iotaledger/wasp/packages/webapi/models" "github.com/iotaledger/wasp/packages/webapi/params" ) -type gasFeePolicy struct { - GasFeeTokenID string `json:"gasFeeTokenId" swagger:"desc(The gas fee token id. Empty if base token.),required"` - GasPerToken string `json:"gasPerToken" swagger:"desc(The amount of gas per token. (uint64 as string)),min(0),required"` - ValidatorFeeShare uint8 `json:"validatorFeeShare" swagger:"desc(The validator fee share.),required"` -} - -type GovChainInfoResponse struct { - ChainID string `json:"chainID" swagger:"desc(ChainID (Bech32-encoded).),required"` - ChainOwnerID string `json:"chainOwnerId" swagger:"desc(The chain owner address (Bech32-encoded).),required"` - Description string `json:"description" swagger:"desc(The description of the chain.),required"` - GasFeePolicy gasFeePolicy `json:"gasFeePolicy" swagger:"desc(The gas fee policy),required"` - MaxBlobSize uint32 `json:"maxBlobSize" swagger:"desc(The maximum contract blob size.),required"` - MaxEventSize uint16 `json:"maxEventSize" swagger:"desc(The maximum event size.),required"` // TODO: Clarify - MaxEventsPerReq uint16 `json:"maxEventsPerReq" swagger:"desc(The maximum amount of events per request.),required"` // TODO: Clarify -} - -type GovAllowedStateControllerAddressesResponse struct { - Addresses []string `json:"addresses" swagger:"desc(The allowed state controller addresses (Bech32-encoded))"` -} - -type GovChainOwnerResponse struct { - ChainOwner string `json:"chainOwner" swagger:"desc(The chain owner (Bech32-encoded))"` -} - -func MapGovChainInfoResponse(chainInfo *governance.ChainInfo) GovChainInfoResponse { +func MapGovChainInfoResponse(chainInfo *governance.ChainInfo) models.GovChainInfoResponse { gasFeeTokenID := "" if !isc.IsEmptyNativeTokenID(chainInfo.GasFeePolicy.GasFeeTokenID) { gasFeeTokenID = chainInfo.GasFeePolicy.GasFeeTokenID.String() } - chainInfoResponse := GovChainInfoResponse{ + chainInfoResponse := models.GovChainInfoResponse{ ChainID: chainInfo.ChainID.String(), ChainOwnerID: chainInfo.ChainOwnerID.String(), Description: chainInfo.Description, - GasFeePolicy: gasFeePolicy{ + GasFeePolicy: models.GasFeePolicy{ GasFeeTokenID: gasFeeTokenID, - GasPerToken: iotago.EncodeUint64(chainInfo.GasFeePolicy.GasPerToken), + GasPerToken: chainInfo.GasFeePolicy.GasPerToken, ValidatorFeeShare: chainInfo.GasFeePolicy.ValidatorFeeShare, + EVMGasRatio: chainInfo.GasFeePolicy.EVMGasRatio, }, MaxBlobSize: chainInfo.MaxBlobSize, MaxEventSize: chainInfo.MaxEventSize, @@ -87,7 +64,7 @@ func (c *Controller) getChainOwner(e echo.Context) error { return c.handleViewCallError(err, chainID) } - chainOwnerResponse := GovChainOwnerResponse{ + chainOwnerResponse := models.GovChainOwnerResponse{ ChainOwner: chainOwner.String(), } @@ -111,7 +88,7 @@ func (c *Controller) getAllowedStateControllerAddresses(e echo.Context) error { encodedAddresses[k] = v.Bech32(parameters.L1().Protocol.Bech32HRP) } - addressesResponse := GovAllowedStateControllerAddressesResponse{ + addressesResponse := models.GovAllowedStateControllerAddressesResponse{ Addresses: encodedAddresses, } diff --git a/packages/webapi/models/chain.go b/packages/webapi/models/chain.go index d470ebb2bd..379b02ea7e 100644 --- a/packages/webapi/models/chain.go +++ b/packages/webapi/models/chain.go @@ -1,7 +1,6 @@ package models import ( - iotago "github.com/iotaledger/iota.go/v3" "github.com/iotaledger/wasp/packages/isc" "github.com/iotaledger/wasp/packages/webapi/dto" ) @@ -51,19 +50,13 @@ type ContractInfoResponse struct { ProgramHash string `json:"programHash" swagger:"desc(The hash of the contract. (Hex encoded)),required"` } -type gasFeePolicy struct { - GasFeeTokenID string `json:"gasFeeTokenId" swagger:"desc(The gas fee token id. Empty if base token.),required"` - GasPerToken string `json:"gasPerToken" swagger:"desc(The amount of gas per token. (uint64 as string)),required"` - ValidatorFeeShare uint8 `json:"validatorFeeShare" swagger:"desc(The validator fee share.),required,min(1)"` -} - type ChainInfoResponse struct { IsActive bool `json:"isActive" swagger:"desc(Whether or not the chain is active.),required"` ChainID string `json:"chainID" swagger:"desc(ChainID (Bech32-encoded).),required"` EVMChainID uint16 `json:"evmChainId" swagger:"desc(The EVM chain ID),required,min(1)"` ChainOwnerID string `json:"chainOwnerId" swagger:"desc(The chain owner address (Bech32-encoded).),required"` Description string `json:"description" swagger:"desc(The description of the chain.),required"` - GasFeePolicy gasFeePolicy `json:"gasFeePolicy"` + GasFeePolicy GasFeePolicy `json:"gasFeePolicy"` MaxBlobSize uint32 `json:"maxBlobSize" swagger:"desc(The maximum contract blob size.),required,min(1)"` MaxEventSize uint16 `json:"maxEventSize" swagger:"desc(The maximum event size.),required,min(1)"` // TODO: Clarify MaxEventsPerReq uint16 `json:"maxEventsPerReq" swagger:"desc(The maximum amount of events per request.),required,min(1)"` // TODO: Clarify @@ -95,10 +88,11 @@ func MapChainInfoResponse(chainInfo *dto.ChainInfo, evmChainID uint16) ChainInfo gasFeeTokenID = chainInfo.GasFeePolicy.GasFeeTokenID.String() } - chainInfoResponse.GasFeePolicy = gasFeePolicy{ + chainInfoResponse.GasFeePolicy = GasFeePolicy{ GasFeeTokenID: gasFeeTokenID, - GasPerToken: iotago.EncodeUint64(chainInfo.GasFeePolicy.GasPerToken), + GasPerToken: chainInfo.GasFeePolicy.GasPerToken, ValidatorFeeShare: chainInfo.GasFeePolicy.ValidatorFeeShare, + EVMGasRatio: chainInfo.GasFeePolicy.EVMGasRatio, } } diff --git a/packages/webapi/models/governance.go b/packages/webapi/models/governance.go new file mode 100644 index 0000000000..0b3c39ea80 --- /dev/null +++ b/packages/webapi/models/governance.go @@ -0,0 +1,28 @@ +package models + +import "github.com/iotaledger/wasp/packages/util" + +type GasFeePolicy struct { + GasFeeTokenID string `json:"gasFeeTokenId" swagger:"desc(The gas fee token id. Empty if base token.),required"` + GasPerToken util.Ratio32 `json:"gasPerToken" swagger:"desc(The gas per token ratio (fee = gas * A/B)),required"` + ValidatorFeeShare uint8 `json:"validatorFeeShare" swagger:"desc(The validator fee share.),required"` + EVMGasRatio util.Ratio32 `json:"evmGasRatio" swagger:"desc(The EVM gas ratio (ISC gas = EVM gas * A/B)),required"` +} + +type GovChainInfoResponse struct { + ChainID string `json:"chainID" swagger:"desc(ChainID (Bech32-encoded).),required"` + ChainOwnerID string `json:"chainOwnerId" swagger:"desc(The chain owner address (Bech32-encoded).),required"` + Description string `json:"description" swagger:"desc(The description of the chain.),required"` + GasFeePolicy GasFeePolicy `json:"gasFeePolicy" swagger:"desc(The gas fee policy),required"` + MaxBlobSize uint32 `json:"maxBlobSize" swagger:"desc(The maximum contract blob size.),required"` + MaxEventSize uint16 `json:"maxEventSize" swagger:"desc(The maximum event size.),required"` // TODO: Clarify + MaxEventsPerReq uint16 `json:"maxEventsPerReq" swagger:"desc(The maximum amount of events per request.),required"` // TODO: Clarify +} + +type GovAllowedStateControllerAddressesResponse struct { + Addresses []string `json:"addresses" swagger:"desc(The allowed state controller addresses (Bech32-encoded))"` +} + +type GovChainOwnerResponse struct { + ChainOwner string `json:"chainOwner" swagger:"desc(The chain owner (Bech32-encoded))"` +} diff --git a/packages/webapi/models/mock/ChainInfoResponse.json b/packages/webapi/models/mock/ChainInfoResponse.json index 5eb832c1c6..35674fb282 100644 --- a/packages/webapi/models/mock/ChainInfoResponse.json +++ b/packages/webapi/models/mock/ChainInfoResponse.json @@ -5,10 +5,11 @@ "description": "", "gasFeePolicy": { "gasFeeTokenId": "", - "gasPerToken": "100", - "validatorFeeShare": 0 + "gasPerToken": {"a": 1, "b": 100}, + "validatorFeeShare": 0, + "evmGasRatio": {"a": 1, "b": 1} }, "maxBlobSize": 2000000, "maxEventSize": 2000, "maxEventsPerReq": 50 -} \ No newline at end of file +} diff --git a/packages/webapi/models/mock/ChainInfoResponse[].json b/packages/webapi/models/mock/ChainInfoResponse[].json index bb310f6616..ea4aaef55d 100644 --- a/packages/webapi/models/mock/ChainInfoResponse[].json +++ b/packages/webapi/models/mock/ChainInfoResponse[].json @@ -6,11 +6,12 @@ "description": "", "gasFeePolicy": { "gasFeeTokenId": "", - "gasPerToken": "100", - "validatorFeeShare": 0 + "gasPerToken": {"a": 1, "b": 100}, + "validatorFeeShare": 0, + "evmGasRatio": {"a": 1, "b": 1} }, "maxBlobSize": 2000000, "maxEventSize": 2000, "maxEventsPerReq": 50 } -] \ No newline at end of file +] diff --git a/tools/cluster/tests/maintenance_test.go b/tools/cluster/tests/maintenance_test.go index a745c0f2cd..fdc7114141 100644 --- a/tools/cluster/tests/maintenance_test.go +++ b/tools/cluster/tests/maintenance_test.go @@ -13,6 +13,7 @@ import ( "github.com/iotaledger/wasp/packages/isc" "github.com/iotaledger/wasp/packages/kv/codec" "github.com/iotaledger/wasp/packages/kv/dict" + "github.com/iotaledger/wasp/packages/util" "github.com/iotaledger/wasp/packages/vm/core/governance" "github.com/iotaledger/wasp/packages/vm/gas" ) @@ -114,7 +115,7 @@ func testMaintenance(t *testing.T, env *ChainEnv) { // calls to governance are processed (try changing fees for example) newGasFeePolicy := gas.GasFeePolicy{ GasFeeTokenID: iotago.NativeTokenID{}, - GasPerToken: 10, + GasPerToken: util.Ratio32{A: 1, B: 10}, ValidatorFeeShare: 1, EVMGasRatio: gas.DefaultEVMGasRatio, } diff --git a/tools/wasp-cli/chain/info.go b/tools/wasp-cli/chain/info.go index d670763be7..6672093c14 100644 --- a/tools/wasp-cli/chain/info.go +++ b/tools/wasp-cli/chain/info.go @@ -99,7 +99,7 @@ func initInfoCmd() *cobra.Command { } } - log.Printf("Gas fee: 1 %s = %v gas units\n", gasFeeToken, chainInfo.GasFeePolicy.GasPerToken) + log.Printf("Gas fee (%s): fee = gas units * (%d/%d)\n", gasFeeToken, chainInfo.GasFeePolicy.GasPerToken.A, chainInfo.GasFeePolicy.GasPerToken.B) log.Printf("Validator fee share: %d%%\n", chainInfo.GasFeePolicy.ValidatorFeeShare) } diff --git a/tools/wasp-cli/decode/cmd.go b/tools/wasp-cli/decode/cmd.go index 2daef324b4..4839e15de2 100644 --- a/tools/wasp-cli/decode/cmd.go +++ b/tools/wasp-cli/decode/cmd.go @@ -96,7 +96,7 @@ func initEncodeGasFeePolicy() *cobra.Command { var ( tokenID string tokenDecimals uint32 - gasPerToken uint64 + gasPerToken string evmGasRatio string validatorFeeShare uint8 ) @@ -119,8 +119,10 @@ func initEncodeGasFeePolicy() *cobra.Command { gasPolicy.GasFeeTokenDecimals = tokenDecimals } - if gasPerToken != 0 { - gasPolicy.GasPerToken = gasPerToken + if gasPerToken != "" { + ratio, err := wasp_util.Ratio32FromString(evmGasRatio) + log.Check(err) + gasPolicy.GasPerToken = ratio } if evmGasRatio != "" { @@ -139,7 +141,7 @@ func initEncodeGasFeePolicy() *cobra.Command { cmd.Flags().StringVar(&tokenID, "tokenID", "", "TokenID for the gas fee") cmd.Flags().Uint32Var(&tokenDecimals, "tokenDecimals", 0, "decimals for the fee token") - cmd.Flags().Uint64Var(&gasPerToken, "gasPerToken", 0, "gas per token") + cmd.Flags().StringVar(&gasPerToken, "gasPerToken", "", "gas per token ratio (format: a:b)") cmd.Flags().StringVar(&evmGasRatio, "evmGasRatio", "", "evm gas ratio (format: a:b)") cmd.Flags().Uint8Var(&validatorFeeShare, "validatorFeeShare", 101, "validator fee share (between 0 and 100)")