Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
88 changes: 88 additions & 0 deletions contracts/validatorcontract/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
# Validator Set Contract

This package contains the reference validator set contract used with QBFT contract-based validator selection.

## Files

- `contract/validator_set.sol`: Solidity source for the validator set contract.
- `contract/validator_set.go`: generated Go binding. Do not edit by hand.
- `validator.go`: small Go wrapper around the generated binding.
- `validator_test.go`: simulated backend tests for the contract behavior.

## Update Flow

1. Edit `contract/validator_set.sol`.
2. Keep the Solidity pragma on a real compiler version supported by the local toolchain. The current source uses Solidity `^0.8.30`.
3. Preserve the QBFT compatibility method:

```solidity
function getValidators() external view returns (address[] memory)
```

QBFT contract mode calls this method and expects it to return the active validator list. In this implementation, validators in maintenance are excluded from the returned list.

4. Compile the contract to temporary Foundry artifacts:

```sh
forge build \
--use 0.8.30 \
--evm-version paris \
--contracts contracts/validatorcontract/contract \
--out /private/tmp/validatorcontract-out \
--cache-path /private/tmp/validatorcontract-cache
```

The `paris` EVM target keeps the generated bytecode compatible with the Go simulated backend used by the tests.

5. Extract ABI and bytecode:

```sh
jq '.abi' /private/tmp/validatorcontract-out/validator_set.sol/ValidatorSet.json \
> /private/tmp/ValidatorSet.abi

jq -r '.bytecode.object' /private/tmp/validatorcontract-out/validator_set.sol/ValidatorSet.json \
> /private/tmp/ValidatorSet.bin
```

6. Regenerate the Go binding:

```sh
go run ./cmd/abigen \
--abi /private/tmp/ValidatorSet.abi \
--bin /private/tmp/ValidatorSet.bin \
--pkg contract \
--type ValidatorSet \
--out contracts/validatorcontract/contract/validator_set.go
```

7. Format generated and handwritten Go files:

```sh
gofmt -w \
contracts/validatorcontract/validator.go \
contracts/validatorcontract/validator_test.go \
contracts/validatorcontract/contract/validator_set.go
```

8. Run tests:

```sh
go test ./contracts/validatorcontract
go test ./contracts/...
```

## Contract Compatibility Rules

- `getValidators()` must remain present with the same signature.
- `getValidators()` must return only active validators.
- Governance quorum is based on all registered validators, not only active validators.
- `faultTolerance()` is calculated as `(N - 1) / 3`, where `N` is the number of registered validators.
- `quorumSize()` is calculated as `2f + 1`.
- Add/remove proposal IDs include the current validator set version, so the same address can be removed, re-added, and removed again in later versions.
- A validator in maintenance still has governance voting power.
- At most `f` validators may be in maintenance at the same time.

## Notes

- The generated binding includes deployment bytecode, so regenerate it whenever the Solidity source changes, including NatSpec-only changes that affect metadata.
- Do not commit temporary Foundry `cache/` or `out/` directories. Prefer the `/private/tmp/...` paths shown above.
1,429 changes: 1,429 additions & 0 deletions contracts/validatorcontract/contract/validator_set.go

Large diffs are not rendered by default.

Loading
Loading