From 48c99474765780a8ac03e852b159cee0bc6c6562 Mon Sep 17 00:00:00 2001 From: JK Date: Fri, 1 Nov 2024 10:10:38 +0100 Subject: [PATCH] Add NodeDriver docs --- contracts/sfc/NodeDriver.sol | 31 ++++++++++++++++++++++++---- contracts/sfc/NodeDriverAuth.sol | 35 ++++++++++++++++++++++++++++---- 2 files changed, 58 insertions(+), 8 deletions(-) diff --git a/contracts/sfc/NodeDriver.sol b/contracts/sfc/NodeDriver.sol index c8979d6..a872184 100644 --- a/contracts/sfc/NodeDriver.sol +++ b/contracts/sfc/NodeDriver.sol @@ -17,11 +17,13 @@ contract NodeDriver is Initializable { event UpdatedBackend(address indexed backend); + /// NodeDriverAuth can replace itself function setBackend(address _backend) external onlyBackend { emit UpdatedBackend(_backend); backend = NodeDriverAuth(_backend); } + /// Callable only by NodeDriverAuth (which mediates calls from SFC and from admins) modifier onlyBackend() { if (msg.sender != address(backend)) { revert NotBackend(); @@ -36,6 +38,8 @@ contract NodeDriver is Initializable { event UpdateNetworkVersion(uint256 version); event AdvanceEpochs(uint256 num); + /// Initialization is called only once, after the contract deployment. + /// Because the contract code is written directly into genesis, constructor cannot be used. function initialize(address _backend, address _evmWriterAddress) external initializer { backend = NodeDriverAuth(_backend); emit UpdatedBackend(_backend); @@ -62,26 +66,38 @@ contract NodeDriver is Initializable { evmWriter.incNonce(acc, diff); } + /// Update network rules configuring the chain. + /// Emitted event is being observed by Sonic client. function updateNetworkRules(bytes calldata diff) external onlyBackend { emit UpdateNetworkRules(diff); } + /// Update advertised version of the network. + /// Emitted event is being observed by Sonic client. function updateNetworkVersion(uint256 version) external onlyBackend { emit UpdateNetworkVersion(version); } + /// Enforce sealing given number of epochs. + /// Emitted event is being observed by Sonic client. function advanceEpochs(uint256 num) external onlyBackend { emit AdvanceEpochs(num); } + /// Update weight of a validator. Used to propagate a stake change from SFC to the client. + /// Emitted event is being observed by Sonic client. function updateValidatorWeight(uint256 validatorID, uint256 value) external onlyBackend { emit UpdateValidatorWeight(validatorID, value); } + /// Update public key of a validator. Used to propagate a change from SFC to the client. + /// Emitted event is being observed by Sonic client. function updateValidatorPubkey(uint256 validatorID, bytes calldata pubkey) external onlyBackend { emit UpdateValidatorPubkey(validatorID, pubkey); } + /// Callable only from Sonic client itself as an internal tx. + /// Used for propagating network event (validator doublesign, epoch sealing) from node to SFC. modifier onlyNode() { if (msg.sender != address(0)) { revert NotNode(); @@ -91,6 +107,7 @@ contract NodeDriver is Initializable { // Methods which are called only by the node + /// Set an initial validator. Called only as part of network initialization/genesis file generating. function setGenesisValidator( address auth, uint256 validatorID, @@ -100,18 +117,18 @@ contract NodeDriver is Initializable { backend.setGenesisValidator(auth, validatorID, pubkey, createdTime); } + /// Set an initial delegation. Called only as part of network initialization/genesis file generating. function setGenesisDelegation(address delegator, uint256 toValidatorID, uint256 stake) external onlyNode { backend.setGenesisDelegation(delegator, toValidatorID, stake); } + /// Deactivate a validator. Called by network node when a double-sign of the given validator is registered. + /// Is called before sealEpoch() call. function deactivateValidator(uint256 validatorID, uint256 status) external onlyNode { backend.deactivateValidator(validatorID, status); } - function sealEpochValidators(uint256[] calldata nextValidatorIDs) external onlyNode { - backend.sealEpochValidators(nextValidatorIDs); - } - + /// Seal epoch. Called BEFORE epoch sealing made by the client itself. function sealEpoch( uint256[] calldata offlineTimes, uint256[] calldata offlineBlocks, @@ -121,6 +138,7 @@ contract NodeDriver is Initializable { backend.sealEpoch(offlineTimes, offlineBlocks, uptimes, originatedTxsFee, 841669690); } + /// Seal epoch. To be called BEFORE epoch sealing made by the client itself - currently not used. function sealEpochV1( uint256[] calldata offlineTimes, uint256[] calldata offlineBlocks, @@ -130,4 +148,9 @@ contract NodeDriver is Initializable { ) external onlyNode { backend.sealEpoch(offlineTimes, offlineBlocks, uptimes, originatedTxsFee, usedGas); } + + /// Seal epoch. Called AFTER epoch sealing made by the client itself. + function sealEpochValidators(uint256[] calldata nextValidatorIDs) external onlyNode { + backend.sealEpochValidators(nextValidatorIDs); + } } diff --git a/contracts/sfc/NodeDriverAuth.sol b/contracts/sfc/NodeDriverAuth.sol index fe87a3d..aaa946e 100644 --- a/contracts/sfc/NodeDriverAuth.sol +++ b/contracts/sfc/NodeDriverAuth.sol @@ -28,6 +28,7 @@ contract NodeDriverAuth is Initializable, Ownable { sfc = ISFC(_sfc); } + /// Callable only by SFC contract. modifier onlySFC() { if (msg.sender != address(sfc)) { revert NotSFC(); @@ -35,6 +36,7 @@ contract NodeDriverAuth is Initializable, Ownable { _; } + /// Callable only by NodeDriver (mediates messages from the network client) modifier onlyDriver() { if (msg.sender != address(driver)) { revert NotDriver(); @@ -42,6 +44,7 @@ contract NodeDriverAuth is Initializable, Ownable { _; } + /// Change NodeDriverAuth used by NodeDriver. Callable by network admin. function migrateTo(address newDriverAuth) external onlyOwner { driver.setBackend(newDriverAuth); } @@ -59,10 +62,16 @@ contract NodeDriverAuth is Initializable, Ownable { } } + /// Execute a batch update of network configuration. + /// Run given contract with a permission of the NodeDriverAuth owner. + /// Does not allow changing NodeDriver and NodeDriverAuth code. function execute(address executable) external onlyOwner { _execute(executable, owner(), _getCodeHash(address(this)), _getCodeHash(address(driver))); } + /// Execute a batch update of network configuration. + /// Run given contract with a permission of the NodeDriverAuth owner. + /// Allows changing NodeDriver and NodeDriverAuth code. function mutExecute( address executable, address newOwner, @@ -72,6 +81,7 @@ contract NodeDriverAuth is Initializable, Ownable { _execute(executable, newOwner, selfCodeHash, driverCodeHash); } + /// Mint native token. To be used by SFC for minting validators rewards. function incBalance(address acc, uint256 diff) external onlySFC { if (acc != address(sfc)) { revert RecipientNotSFC(); @@ -79,6 +89,8 @@ contract NodeDriverAuth is Initializable, Ownable { driver.setBalance(acc, address(acc).balance + diff); } + /// Upgrade code of given contract by coping it from other deployed contract. + /// Avoids setting code to an external address. function upgradeCode(address acc, address from) external onlyOwner { if (!isContract(acc) || !isContract(from)) { revert NotContract(); @@ -86,39 +98,49 @@ contract NodeDriverAuth is Initializable, Ownable { driver.copyCode(acc, from); } + /// Upgrade code of given contract by coping it from other deployed contract. + /// Does not avoid setting code to an external address. (DANGEROUS!) function copyCode(address acc, address from) external onlyOwner { driver.copyCode(acc, from); } + /// Increment nonce of the given account. function incNonce(address acc, uint256 diff) external onlyOwner { driver.incNonce(acc, diff); } + /// Update network rules by providing a JSON patch. function updateNetworkRules(bytes calldata diff) external onlyOwner { driver.updateNetworkRules(diff); } + /// Update MinGasPrice. Called by SFC during epoch sealing. function updateMinGasPrice(uint256 minGasPrice) external onlySFC { // prettier-ignore driver.updateNetworkRules(bytes(strConcat("{\"Economy\":{\"MinGasPrice\":", uint256ToStr(minGasPrice), "}}"))); } + /// Update advertised network version. function updateNetworkVersion(uint256 version) external onlyOwner { driver.updateNetworkVersion(version); } + /// Enforce sealing given number of epochs. function advanceEpochs(uint256 num) external onlyOwner { driver.advanceEpochs(num); } + /// Update weight of a validator. Used to propagate a stake change from SFC to the client. function updateValidatorWeight(uint256 validatorID, uint256 value) external onlySFC { driver.updateValidatorWeight(validatorID, value); } + /// Update public key of a validator. Used to propagate a change from SFC to the client. function updateValidatorPubkey(uint256 validatorID, bytes calldata pubkey) external onlySFC { driver.updateValidatorPubkey(validatorID, pubkey); } + /// Set an initial validator into SFC. Called only as part of network initialization/genesis file generating. function setGenesisValidator( address auth, uint256 validatorID, @@ -128,18 +150,18 @@ contract NodeDriverAuth is Initializable, Ownable { sfc.setGenesisValidator(auth, validatorID, pubkey, createdTime); } + /// Set an initial delegation. Called only as part of network initialization/genesis file generating. function setGenesisDelegation(address delegator, uint256 toValidatorID, uint256 stake) external onlyDriver { sfc.setGenesisDelegation(delegator, toValidatorID, stake); } + /// Deactivate a validator. Called by network node when a double-sign of the given validator is registered. + /// Is called before sealEpoch() call. function deactivateValidator(uint256 validatorID, uint256 status) external onlyDriver { sfc.deactivateValidator(validatorID, status); } - function sealEpochValidators(uint256[] calldata nextValidatorIDs) external onlyDriver { - sfc.sealEpochValidators(nextValidatorIDs); - } - + /// Seal epoch. Called BEFORE epoch sealing made by the client itself. function sealEpoch( uint256[] calldata offlineTimes, uint256[] calldata offlineBlocks, @@ -150,6 +172,11 @@ contract NodeDriverAuth is Initializable, Ownable { sfc.sealEpoch(offlineTimes, offlineBlocks, uptimes, originatedTxsFee, usedGas); } + /// Seal epoch. Called AFTER epoch sealing made by the client itself. + function sealEpochValidators(uint256[] calldata nextValidatorIDs) external onlyDriver { + sfc.sealEpochValidators(nextValidatorIDs); + } + function isContract(address account) internal view returns (bool) { uint256 size; // solhint-disable-next-line no-inline-assembly