Skip to content

Latest commit

 

History

History
263 lines (238 loc) · 11.4 KB

fip-0012.md

File metadata and controls

263 lines (238 loc) · 11.4 KB
fip title status type author created updated
12
Move action whitelisting into state
Final
Functionality
Ed Rotthoff <ed@dapix.io>, Pawel Mastalerz <pawel@dapix.io>
07/06/2020
09/25/2020

Release: fio v2.0.0, fio.contracts v2.0.0

Abstract

This FIP moves action whitelisting into state, so that new actions being added to the FIO Protocol do not require a coordinated FIO Chain software update.

Proposed new actions:

Action Endpoint Description
addaction Adds new action to state table.
remaction Removes action from state table.
get_actions Fetches a whitelisted actions from state table.

Motivation

This FIO protocol uses a whitelist of actions to prohibit unknown actions from spamming the network. The whitelist is implemented in the FIO Protocol core code. This means that any new action added to the FIO Protocol needs to be added to the whitelist and that requires a mandatory upgrade of the FIO Chain software. This is undesirable because it requires coordinated deployment of new software version to avoid hard fork. A better approach is to enable modifications to the whitelist via on-chain contract update performed by consensus of top 21 Block Producers.

Specification

New actions

Add action

Adds new action to state table.

New action: addaction

New endpoint: None, this will always be performed via push_transaction

New fee: no fee, this is an administrative action performed by consensus of top 21 Block Producers, not bundle-eligible

RAM increase: no RAM bump

Request

Parameter Required Format Definition
action Yes name This is the action name being added to the FIO protocol contracts.
contract Yes string The name of the contract that owns this action, EX: "fio.token"
actor Yes 12 character string Valid actor of signer
Example
{
	"action": "newaction",
	"contract": "fio.token",
	"actor": "fio.system"
}

Processing

  • Require auth of actor.
  • require actor is one of the fio.system accounts (error if the auth is NOT a fio system account)
  • Verify action name is not empty.
  • Verify contract string is not empty.
  • Check if the action name is already in the action mapping, if it is there then 400 error.
  • Get the current FIO block time.
  • Add the new action mapping to the actions table in state.

Exception handling

Error condition Trigger Type fields:name fields:value Error message
Invalid action action is not valid 500 “Action invalid or not found'
Invalid contract contract_string is not valid 500 “Invalid Contract"
Invalid authorization Signing authorization is not valid 500 “missing authority of "

Response

Parameter Format Definition
status String OK if successful
Example
{
	"status": "OK"
}

Remove action

Removes action from state table.

New action: remaction

New endpoint: None, this will always be performed via push_transaction

New fee: no fee, this is an administrative action performed by consensus of top 21 Block Producers, not bundle-eligible

RAM increase: no RAM bump

Request

Parameter Required Format Definition
action Yes name This is the action name being removed.
actor Yes 12 character string Valid actor of signer
Example
{
	"action": "newaction"
}

Processing

  • Require auth of actor.
  • require actor is one of the fio.system accounts (error if the auth is NOT a fio system account)
  • Verify action name is not empty.
  • Check if the action name exists in the action mapping, if NOT then this is a 400 error.
  • Remove the action mapping from the actions table in state.

Exception handling

Error condition Trigger Type fields:name fields:value Error message
Invalid action action is not valid or not found 500 “Internal Service Error - (fc)
Invalid authorization Signing authorization is not valid 500 “Internal Service Error - (fc)

Response

Parameter Format Definition
status String OK if successful
Example
{
	"status": "OK"
}

Fetch whitelisted actions

Fetches a whitelisted actions from state table.

New action: None

New endpoint: /get_actions

Request

Parameter Required Format Definition
limit No Positive Int Number of records to return. If omitted, all records will be returned. Due to table read timeout, a value of less than 1,000 is recommended.
offset No Positive Int First record from list to return. If omitted, 0 is assumed.
Example
{
	"limit": 5,
	"offset": 2
}

Processing

  • Verify limit and offset if they are present (not negative, if negative 400 error)
  • Query the table in state and return the resulting rows.

Exception handling

Error condition Trigger Type fields:name fields:value Error message
Invalid limit limit is not valid 400 "limit" Value sent in, e.g. "-1" "Invalid limit"
invalid offset offset not valid 400 "offset" Value sent in, e.g. "-1" "Invalid offset"

Response

Group Parameter Format Definition
actions JSON Array Array of actions
actions action name Action name
actions contract String Contract name
actions block_timestamp Int Blocktime when action added
more Int Number of remaining results
Example
{
	"actions": [
		{
			"action": "newaction1",
			"contract": "fio.token",
			"block_timestamp": 1234456667
		},
		{
			"action": "newaction2",
			"contract": "fio.token",
			"block_timestamp": 1234456765
		},
		{
			"action_name": "newaction3",
			"contract": "fio.token",
			"block_timestamp": 1234456765
		}
	],
	"more": 5
}

Changes to existing actions

serialize_json

serialize_json will be modified to use the mapping from state instead of using the action mapping coded into the code.

Rationale

Storing new actions in state is deemed the best strategy to allow on-chain updates to whitelisted actions.

Implementation

Overview

We create a new table in state with primary key Id, and secondary key being the action name, this will allow adequate paging and also adequate lookup by action name.

Details

Add a new table to the eosio_contract that holds FioAction objects (see below).

  • add a new class called fio_action.hpp (use account_object as example). use fioAction object below.
  • add new types to types.hpp
  • add your new index to the controller.cpp indices.

Add a new callback for the action into the eosio_contract.cpp

  • add new apply_eosio_updateacts to eosio_contract.cpp
  • add new type to contract_types.hpp

Add the new action to the eosio_contract_abi file.

  • add new updateacts action to eosio_contract_abi.cpp

Plug in the contract action handler, into the controller.

  • add new SET_APP_HANDLER call to controller.cpp (around line 340)

Add the new post action callback to the eosio system contract.

  • add new action updateacts to native.hpp for system contract. this action just needs one line check auth fio system contract.
  • add new struct to contract_types.hpp for updateacts params and get_account and get_name

Data structures

  • FioActions contains a vector
  • FioAction is a struct
  • name actionname
  • string contractnam
  • uint64 timestamp. Block time when added (set to zero for “available at main net”)

apply_context.cpp

Apply context —

  • get the present block time.
  • get the action from the tx.
  • if its after the hard fork block, and if there is data in the actions table (note set this block time to be some time after the community is notified, to allow time for the MSIG to update the actions table to execute, the only check necessary might be to just check that the actions table is not empty). This logic could be further distilled to just check for the existence of the new table (with records), and if its there then use it, otherwise do the old logic.
  • read the actions table by name.
  • If action doesn’t exist in actions table then error.
  • If action exists in actions table
  • If present block time <= timestamp Error
  • else if its before the hard fork block time, or if the actions table is empty
  • do the existing logic.

chain_plugin.cpp

Serialize json —

  • if there are entries in the actions table, or if its after a pre-determined block time then
  • Use db.get style access to check if the action is in the actions table.
  • If its not in the list then error.
  • If its there then get the contract name and use it.
  • else
  • Use the existing logic.

Backwards Compatibility

Ensure that a soft fork plan is put into place that identifies the block time after which the MSIG to set the new contract into place will be executed. Two drop dead times need to be identified, first, the date/time at which all BPs, API nodes, and exchanges must be updated with the new version, then secondly the date/time by which the MSIG will be executed to put into place the new contract version. This second block time will be the time coded into the forking logic in the code.

Future considerations

None

Testing Plan

The following development testing plan has been completed for these changes.

  • A 21 node private test net was created with 3 nodes in the boot cluster, and then 6 nodes in each of the 3 test node clusters. A detailed description of the Dapix private test net and the automated operations which it supports can be provided if this is desirable. The implementation is presently available in the dapixio/dev-net repository on the github.

  • The entire 21 node test net was initially brought up with contracts and core code at FIO v1.0.5.

  • Java script tests have been developed for 1.0.5 and these were run as indicated.

  • First the forking block time was set to 3pm MST on the day of the tests. (this is the version of the code used in testing)

  • The tests were run.

  • 6 of the test nodes (cluster A) were upgraded to the gemini code version.

  • The tests were run.

  • 6 more of the test nodes (cluster C) were upgraded to the gemini code version.

  • The tests were run.

  • 6 more of the test nodes (cluster B) were upgraded to the gemini version.

  • The tests were run.

  • The set code was executed to add the addaction and removeaction for whitelisting to the FIO system contract.

  • a script was used to call add action for all but 16 of the actions presently permitted by the FIO protocol (this was done so that we can call one of the actions not yet set after the forking deadline and prove the new logic is being used). it was observed that the boot cluster (which was not upgraded) "forked out" when the script was run, this was expected.

  • we executed the action (not yet added by addaction, regaddress) before the forking deadline arrived, we noted that the transaction executed as expected because before the forking deadline we are using the action mapping coded into the core code.

  • testing continued (we waited for the forking deadline of 3pm to pass).

  • after the forking deadline we invoked one the action again not yet set by addaction it was observed that this resulted in an error "unknown action in contract".

  • we then ran a script to set the remaining actions using addaction.

  • we then invoked the action again, it was observed the transaction executed as expected.

  • we then ran the javascript tests one last time. (please note -- all javascript tests passed as expected).