Skip to content

Commit

Permalink
Merge pull request #36 from oasysgames/dev-v1.1.0
Browse files Browse the repository at this point in the history
Updates for v1.1.0
  • Loading branch information
ironbeer authored Jun 14, 2023
2 parents 9361854 + 620d4c7 commit 72aafde
Show file tree
Hide file tree
Showing 13 changed files with 764 additions and 187 deletions.
20 changes: 3 additions & 17 deletions .github/setup_template.sh
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,6 @@ if ! unzip -h >/dev/null 2>&1; then
fi

# Ask for parameters.
ask "Select a network [1: mainnet, 2: testnet]" NETWORK 1
ask "Enter the binary installation path" INSTALL_PATH "/usr/local/bin/geth"
ask "Enter the os user name of systemd service" SERVICE_USER "geth"
ask "Enter the passphrase for the private key" PASSPHRASE "" "-s"
Expand All @@ -109,22 +108,9 @@ if [ -z "$PASSPHRASE" ]; then
exit 1
fi

case "$NETWORK" in
1)
NETWORK=mainnet
NETWORK_ID=248
BOOTNODES="enode://1e68361cb0e761e0789c014acdbd2491f30176acf25480408382916632e58af1711d857c75be5917319d06049937e49c09ca51a28590e6ee22aceca1161fd583@3.113.207.39:30301,enode://24a55fd923d780213d15f5551bcbb7171343ef095512927d91baca3e7917124c679f894282eefec37350088b31c45a49bb28df790eb88f487ad60a9b6ccc8f3b@35.238.159.190:30301"
;;
2)
NETWORK=testnet
NETWORK_ID=9372
BOOTNODES="enode://4a85df39ec500acd31d4b9feeea1d024afee5e8df4bc29325c2abf2e0a02a34f6ece24aca06cb5027675c167ecf95a9fc23fb7a0f671f84edb07dafe6e729856@34.142.254.12:30301"
;;
*)
msg_err "Select 1 or 2 for the network."
exit 1
esac

NETWORK=mainnet
NETWORK_ID=248
BOOTNODES="enode://1e68361cb0e761e0789c014acdbd2491f30176acf25480408382916632e58af1711d857c75be5917319d06049937e49c09ca51a28590e6ee22aceca1161fd583@3.113.207.39:30301,enode://24a55fd923d780213d15f5551bcbb7171343ef095512927d91baca3e7917124c679f894282eefec37350088b31c45a49bb28df790eb88f487ad60a9b6ccc8f3b@35.238.159.190:30301"
HOME_DIR=/home/$SERVICE_USER
WALLET_FILE=$HOME_DIR/.ethereum/wallet.txt
PASSWORD_FILE=$HOME_DIR/.ethereum/password.txt
Expand Down
5 changes: 4 additions & 1 deletion .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,8 @@
url = https://github.com/ipsilon/evm-benchmarks
shallow = true
[submodule "consensus/oasys/oasys-genesis-contract"]
path = consensus/oasys/oasys-genesis-contract
path = consensus/oasys/oasys-genesis-contract-cfb3cd0
url = https://github.com/oasysgames/oasys-genesis-contract.git
[submodule "oasys-genesis-contract-6037082"]
path = consensus/oasys/oasys-genesis-contract-6037082
url = https://github.com/oasysgames/oasys-genesis-contract.git
223 changes: 178 additions & 45 deletions consensus/oasys/contract.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"fmt"
"math"
"math/big"
"path/filepath"

"github.com/ethereum/go-ethereum"
"github.com/ethereum/go-ethereum/accounts"
Expand All @@ -29,52 +30,65 @@ import (

const (
// Oasys genesis contracts
environmentAddress = "0x0000000000000000000000000000000000001000"
stakeManagerAddress = "0x0000000000000000000000000000000000001001"
allowListAddress = "0x0000000000000000000000000000000000001002"
environmentAddress = "0x0000000000000000000000000000000000001000"
stakeManagerAddress = "0x0000000000000000000000000000000000001001"
allowListAddress = "0x0000000000000000000000000000000000001002"
candidateManagerAddress = "0x520000000000000000000000000000000000002e"
)

var (
//go:embed oasys-genesis-contract/artifacts/contracts/Environment.sol/Environment.json
//go:embed oasys-genesis-contract/artifacts/contracts/StakeManager.sol/StakeManager.json
//go:embed oasys-genesis-contract-cfb3cd0/artifacts/contracts/Environment.sol/Environment.json
//go:embed oasys-genesis-contract-cfb3cd0/artifacts/contracts/StakeManager.sol/StakeManager.json
//go:embed oasys-genesis-contract-6037082/artifacts/contracts/CandidateValidatorManager.sol/CandidateValidatorManager.json
artifacts embed.FS

// Oasys genesis contracts
environment = &systemContract{
environment = &genesisContract{
address: common.HexToAddress(environmentAddress),
artifact: &artifact{
path: "oasys-genesis-contract/artifacts/contracts/Environment.sol/Environment.json",
path: filepath.FromSlash("oasys-genesis-contract-cfb3cd0/artifacts/contracts/Environment.sol/Environment.json"),
},
}
stakeManager = &systemContract{
stakeManager = &genesisContract{
address: common.HexToAddress(stakeManagerAddress),
artifact: &artifact{
path: "oasys-genesis-contract/artifacts/contracts/StakeManager.sol/StakeManager.json",
path: filepath.FromSlash("oasys-genesis-contract-cfb3cd0/artifacts/contracts/StakeManager.sol/StakeManager.json"),
},
}
genesisContracts = map[common.Address]bool{
environment.address: true,
stakeManager.address: true,
systemMethods = map[*genesisContract]map[string]int{
// Methods with the `onlyCoinbase` modifier are system methods.
// See: https://github.com/oasysgames/oasys-genesis-contract/search?q=onlyCoinbase
environment: {"initialize": 0, "updateValue": 0},
stakeManager: {"initialize": 0, "slash": 0},
}

candidateManager = &builtinContract{
address: common.HexToAddress(candidateManagerAddress),
artifact: &artifact{
path: filepath.FromSlash("oasys-genesis-contract-6037082/artifacts/contracts/CandidateValidatorManager.sol/CandidateValidatorManager.json"),
},
}
)

func init() {
// Parse the system contract ABI
contracts := []*systemContract{environment, stakeManager}
for _, contract := range contracts {
rawData, err := artifacts.ReadFile(contract.artifact.path)
if err != nil {
panic(err)
}
if err = json.Unmarshal(rawData, contract.artifact); err != nil {
panic(err)
}
if err := environment.parseABI(); err != nil {
panic(err)
}
if err := stakeManager.parseABI(); err != nil {
panic(err)
}
if err := candidateManager.parseABI(); err != nil {
panic(err)
}

ABI, err := abi.JSON(bytes.NewReader(contract.artifact.Abi))
if err != nil {
panic(err)
// Check if the ABI includes system methods
for contract, methods := range systemMethods {
for method := range methods {
if _, ok := contract.abi.Methods[method]; !ok {
panic(fmt.Sprintf("Method `%s` does not exist", method))
}
}
contract.abi = &ABI
}
}

Expand All @@ -85,19 +99,43 @@ type artifact struct {
DeployedBytecode string `json:"deployedBytecode"`
}

// systemContract
type systemContract struct {
// contract
type contract struct {
address common.Address
abi *abi.ABI
artifact *artifact
}

func (s *systemContract) verifyCode(state *state.StateDB) bool {
deployed := state.GetCode(s.address)
expect := common.FromHex(s.artifact.DeployedBytecode)
func (b *contract) parseABI() error {
rawData, err := artifacts.ReadFile(b.artifact.path)
if err != nil {
return err
}
if err = json.Unmarshal(rawData, b.artifact); err != nil {
return err
}

ABI, err := abi.JSON(bytes.NewReader(b.artifact.Abi))
if err != nil {
return err
}
b.abi = &ABI

return nil
}

// Contracts deployed in the genesis block
type genesisContract = contract

func (g *genesisContract) verifyCode(state *state.StateDB) bool {
deployed := state.GetCode(g.address)
expect := common.FromHex(g.artifact.DeployedBytecode)
return bytes.Equal(deployed, expect)
}

// Contracts deployed in a hard fork.
type builtinContract = contract

// chainContext
type chainContext struct {
Chain consensus.ChainHeaderReader
Expand Down Expand Up @@ -160,15 +198,15 @@ func (p *environmentValue) Copy() *environmentValue {
}
}

// getNextValidatorsResult
type getNextValidatorsResult struct {
// nextValidators
type nextValidators struct {
Owners []common.Address
Operators []common.Address
Stakes []*big.Int
}

func (p *getNextValidatorsResult) Copy() *getNextValidatorsResult {
cpy := getNextValidatorsResult{
func (p *nextValidators) Copy() *nextValidators {
cpy := nextValidators{
Owners: make([]common.Address, len(p.Owners)),
Operators: make([]common.Address, len(p.Operators)),
Stakes: make([]*big.Int, len(p.Stakes)),
Expand All @@ -181,7 +219,7 @@ func (p *getNextValidatorsResult) Copy() *getNextValidatorsResult {
return &cpy
}

func (p *getNextValidatorsResult) Exists(validator common.Address) bool {
func (p *nextValidators) Exists(validator common.Address) bool {
for _, operator := range p.Operators {
if validator == operator {
return true
Expand Down Expand Up @@ -219,20 +257,37 @@ func (m callmsg) Value() *big.Int { return m.CallMsg.Value }
func (m callmsg) Data() []byte { return m.CallMsg.Data }

func (c *Oasys) IsSystemTransaction(tx *types.Transaction, header *types.Header) (bool, error) {
// deploy transaction
if tx.To() == nil {
return false, nil
}
sender, err := types.Sender(c.txSigner, tx)
if err != nil {

if sender, err := types.Sender(c.txSigner, tx); err != nil {
return false, errors.New("unauthorized transaction")
} else if sender != header.Coinbase {
// not created by validator
return false, nil
}
if sender == header.Coinbase && genesisContracts[*tx.To()] && tx.GasPrice().Cmp(common.Big0) == 0 {
return true, nil

for contract, methods := range systemMethods {
if contract.address != *tx.To() {
continue
}

if called, err := contract.abi.MethodById(tx.Data()); err != nil {
return false, nil
} else if _, ok := methods[called.RawName]; ok {
log.Info("System method transacted",
"validator", header.Coinbase.Hex(), "tx", tx.Hash().Hex(),
"contract", contract.address.Hex(), "method", called.RawName)
return true, nil
}
}

return false, nil
}

// update functions
// Transact the `Environment.initialize` and `StakeManager.initialize` method.
func (c *Oasys) initializeSystemContracts(
state *state.StateDB,
header *types.Header,
Expand Down Expand Up @@ -274,6 +329,7 @@ func (c *Oasys) initializeSystemContracts(
return nil
}

// Transact the `StakeManager.slash` method.
func (c *Oasys) slash(
validator common.Address,
schedule map[uint64]common.Address,
Expand Down Expand Up @@ -305,16 +361,30 @@ type blockchainAPI interface {
}

// view functions
func getNextValidators(ethAPI blockchainAPI, hash common.Hash, epoch uint64) (*getNextValidatorsResult, error) {
func getNextValidators(
config *params.ChainConfig,
ethAPI blockchainAPI,
hash common.Hash,
epoch uint64,
block uint64,
) (*nextValidators, error) {
if config.IsForkedOasysPublication(new(big.Int).SetUint64(block)) {
return callGetHighStakes(ethAPI, hash, epoch)
}
return callGetValidators(ethAPI, hash, epoch)
}

// Call the `StakeManager.getValidators` method.
func callGetValidators(ethAPI blockchainAPI, hash common.Hash, epoch uint64) (*nextValidators, error) {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()

var (
method = "getValidators"
result getNextValidatorsResult
bepoch = big.NewInt(int64(epoch))
result nextValidators
bepoch = new(big.Int).SetUint64(epoch)
cursor = big.NewInt(0)
howMany = big.NewInt(200)
howMany = big.NewInt(100)
)
for {
data, err := stakeManager.abi.Pack(method, bepoch, cursor, howMany)
Expand Down Expand Up @@ -361,6 +431,67 @@ func getNextValidators(ethAPI blockchainAPI, hash common.Hash, epoch uint64) (*g
return &result, nil
}

// Call the `CandidateValidatorManager.getHighStakes` method.
func callGetHighStakes(ethAPI blockchainAPI, hash common.Hash, epoch uint64) (*nextValidators, error) {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()

var (
method = "getHighStakes"
result nextValidators
bpoch = new(big.Int).SetUint64(epoch)
cursor = big.NewInt(0)
howMany = big.NewInt(100)
)
for {
data, err := candidateManager.abi.Pack(method, bpoch, cursor, howMany)
if err != nil {
return nil, err
}

hexData := (hexutil.Bytes)(data)
rbytes, err := ethAPI.Call(
ctx,
ethapi.TransactionArgs{
To: &candidateManager.address,
Data: &hexData,
},
rpc.BlockNumberOrHashWithHash(hash, false),
nil)
if err != nil {
return nil, err
}

var recv struct {
Owners []common.Address
Operators []common.Address
Stakes []*big.Int
Candidates []bool
NewCursor *big.Int

// unused
Actives, Jailed []bool
}
if err := candidateManager.abi.UnpackIntoInterface(&recv, method, rbytes); err != nil {
return nil, err
} else if len(recv.Owners) == 0 {
break
}

cursor = recv.NewCursor
for i := range recv.Owners {
if recv.Candidates[i] {
result.Owners = append(result.Owners, recv.Owners[i])
result.Operators = append(result.Operators, recv.Operators[i])
result.Stakes = append(result.Stakes, recv.Stakes[i])
}
}
}

return &result, nil
}

// Call the `StakeManager.getValidatorOwners` method.
func getValidatorOwners(ethAPI blockchainAPI, hash common.Hash) ([]common.Address, error) {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
Expand All @@ -369,7 +500,7 @@ func getValidatorOwners(ethAPI blockchainAPI, hash common.Hash) ([]common.Addres
method = "getValidatorOwners"
result []common.Address
cursor = big.NewInt(0)
howMany = big.NewInt(200)
howMany = big.NewInt(100)
)
for {
data, err := stakeManager.abi.Pack(method, cursor, howMany)
Expand Down Expand Up @@ -407,6 +538,7 @@ func getValidatorOwners(ethAPI blockchainAPI, hash common.Hash) ([]common.Addres
return result, nil
}

// Call the `StakeManager.getTotalRewards` method.
func getRewards(ethAPI blockchainAPI, hash common.Hash) (*big.Int, error) {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
Expand Down Expand Up @@ -465,6 +597,7 @@ func getRewards(ethAPI blockchainAPI, hash common.Hash) (*big.Int, error) {
return result, nil
}

// Call the `Environment.nextValue` method.
func getNextEnvironmentValue(ethAPI blockchainAPI, hash common.Hash) (*environmentValue, error) {
method := "nextValue"

Expand Down
Loading

0 comments on commit 72aafde

Please sign in to comment.