forked from 0xPolygon/polygon-edge
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Permission smart contract deployment (0xPolygon#692)
* Add contract deployment whitelist CLI commands * Validate smart contract deployment in txPool * Remove whitelist from genesis if nill * code clean up * Fix linter errors * Add command for listing all whitelists * Add unit tests * Typo, replace comma with dot * Fix typo in addAddress flag * Convert flags to snake-case * Alocate arrays to specific size * Fix comment for adding addresses * Make deployment result omitempty * change show command description * Fix typo in whitelist command description * Change permission smart contract error * Make global test var local * Extract errors * Make deployment whitelist key const * Remove genesis config dependecy from show command * Fix lint * extract unmarshalling raw addresses * Switch commands to kebab-case * Refactor unmarshall raw address * Fix lint * Remove test * make addressExists exportable * make canDeployContract helper method * Rename methods * Rename attribute * Reserve space for whitelist * Rename config param * extract config helper to seperate file * Change methods names * Optimize list insertion and deletion * Tidy whotelist object in command * Fix variable names * Tidy txpool * Rename typo * Extract init deploymentWhitelist * Remove unused methods * Remove canDeploy method
- Loading branch information
1 parent
5d2db1e
commit 74ab62e
Showing
14 changed files
with
590 additions
and
12 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
package deployment | ||
|
||
import ( | ||
"fmt" | ||
|
||
"github.com/0xPolygon/polygon-edge/command" | ||
"github.com/spf13/cobra" | ||
) | ||
|
||
func GetCommand() *cobra.Command { | ||
deploymentCmd := &cobra.Command{ | ||
Use: "deployment", | ||
Short: "Top level command for updating smart contract deployment whitelist. Only accepts subcommands", | ||
PreRunE: runPreRun, | ||
Run: runCommand, | ||
} | ||
|
||
setFlags(deploymentCmd) | ||
|
||
return deploymentCmd | ||
} | ||
|
||
func setFlags(cmd *cobra.Command) { | ||
cmd.Flags().StringVar( | ||
¶ms.genesisPath, | ||
chainFlag, | ||
fmt.Sprintf("./%s", command.DefaultGenesisFileName), | ||
"the genesis file to update", | ||
) | ||
cmd.Flags().StringArrayVar( | ||
¶ms.addAddressRaw, | ||
addAddressFlag, | ||
[]string{}, | ||
"adds a new address to the contract deployment whitelist", | ||
) | ||
|
||
cmd.Flags().StringArrayVar( | ||
¶ms.removeAddressRaw, | ||
removeAddressFlag, | ||
[]string{}, | ||
"removes a new address from the contract deployment whitelist", | ||
) | ||
} | ||
|
||
func runPreRun(_ *cobra.Command, _ []string) error { | ||
return params.initRawParams() | ||
} | ||
|
||
func runCommand(cmd *cobra.Command, _ []string) { | ||
outputter := command.InitializeOutputter(cmd) | ||
defer outputter.WriteOutput() | ||
|
||
if err := params.updateGenesisConfig(); err != nil { | ||
outputter.SetError(err) | ||
|
||
return | ||
} | ||
|
||
if err := params.overrideGenesisConfig(); err != nil { | ||
outputter.SetError(err) | ||
|
||
return | ||
} | ||
|
||
outputter.SetCommandResult(params.getResult()) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,162 @@ | ||
package deployment | ||
|
||
import ( | ||
"fmt" | ||
"os" | ||
|
||
"github.com/0xPolygon/polygon-edge/chain" | ||
"github.com/0xPolygon/polygon-edge/command" | ||
"github.com/0xPolygon/polygon-edge/command/helper" | ||
"github.com/0xPolygon/polygon-edge/helper/config" | ||
"github.com/0xPolygon/polygon-edge/types" | ||
) | ||
|
||
const ( | ||
chainFlag = "chain" | ||
addAddressFlag = "add" | ||
removeAddressFlag = "remove" | ||
) | ||
|
||
var ( | ||
params = &deploymentParams{} | ||
) | ||
|
||
type deploymentParams struct { | ||
// raw addresses, entered by CLI commands | ||
addAddressRaw []string | ||
removeAddressRaw []string | ||
|
||
// addresses, converted from raw addresses | ||
addAddresses []types.Address | ||
removeAddresses []types.Address | ||
|
||
// genesis file | ||
genesisPath string | ||
genesisConfig *chain.Chain | ||
|
||
// deployment whitelist from genesis configuration | ||
whitelist []types.Address | ||
} | ||
|
||
func (p *deploymentParams) initRawParams() error { | ||
// convert raw addresses to appropriate format | ||
if err := p.initRawAddresses(); err != nil { | ||
return err | ||
} | ||
|
||
// init genesis configuration | ||
if err := p.initChain(); err != nil { | ||
return err | ||
} | ||
|
||
return nil | ||
} | ||
|
||
func (p *deploymentParams) initRawAddresses() error { | ||
// convert addresses to be added from string to type.Address | ||
p.addAddresses = unmarshallRawAddresses(p.addAddressRaw) | ||
|
||
// convert addresses to be removed from string to type.Address | ||
p.removeAddresses = unmarshallRawAddresses(p.removeAddressRaw) | ||
|
||
return nil | ||
} | ||
|
||
func (p *deploymentParams) initChain() error { | ||
// import genesis configuration | ||
cc, err := chain.Import(p.genesisPath) | ||
if err != nil { | ||
return fmt.Errorf( | ||
"failed to load chain config from %s: %w", | ||
p.genesisPath, | ||
err, | ||
) | ||
} | ||
|
||
// set genesis configuration | ||
p.genesisConfig = cc | ||
|
||
return nil | ||
} | ||
|
||
func (p *deploymentParams) updateGenesisConfig() error { | ||
// Fetch contract deployment whitelist from genesis config | ||
deploymentWhitelist, err := config.GetDeploymentWhitelist(p.genesisConfig) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
doesExist := map[types.Address]bool{} | ||
|
||
for _, a := range deploymentWhitelist { | ||
doesExist[a] = true | ||
} | ||
|
||
for _, a := range p.addAddresses { | ||
doesExist[a] = true | ||
} | ||
|
||
for _, a := range p.removeAddresses { | ||
doesExist[a] = false | ||
} | ||
|
||
newDeploymentWhitelist := make([]types.Address, 0) | ||
|
||
for addr, exists := range doesExist { | ||
if exists { | ||
newDeploymentWhitelist = append(newDeploymentWhitelist, addr) | ||
} | ||
} | ||
|
||
// Set whitelist in genesis configuration | ||
whitelistConfig := config.GetWhitelist(p.genesisConfig) | ||
|
||
if whitelistConfig == nil { | ||
whitelistConfig = &chain.Whitelists{} | ||
} | ||
|
||
whitelistConfig.Deployment = newDeploymentWhitelist | ||
p.genesisConfig.Params.Whitelists = whitelistConfig | ||
|
||
// Save whitelist for result | ||
p.whitelist = newDeploymentWhitelist | ||
|
||
return nil | ||
} | ||
|
||
func (p *deploymentParams) overrideGenesisConfig() error { | ||
// Remove the current genesis configuration from the disk | ||
if err := os.Remove(p.genesisPath); err != nil { | ||
return err | ||
} | ||
|
||
// Save the new genesis configuration | ||
if err := helper.WriteGenesisConfigToDisk( | ||
p.genesisConfig, | ||
p.genesisPath, | ||
); err != nil { | ||
return err | ||
} | ||
|
||
return nil | ||
} | ||
|
||
func (p *deploymentParams) getResult() command.CommandResult { | ||
result := &DeploymentResult{ | ||
AddAddresses: p.addAddresses, | ||
RemoveAddresses: p.removeAddresses, | ||
Whitelist: p.whitelist, | ||
} | ||
|
||
return result | ||
} | ||
|
||
func unmarshallRawAddresses(addresses []string) []types.Address { | ||
marshalledAddresses := make([]types.Address, len(addresses)) | ||
|
||
for indx, address := range addresses { | ||
marshalledAddresses[indx] = types.StringToAddress(address) | ||
} | ||
|
||
return marshalledAddresses | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
package deployment | ||
|
||
import ( | ||
"bytes" | ||
"fmt" | ||
|
||
"github.com/0xPolygon/polygon-edge/types" | ||
) | ||
|
||
type DeploymentResult struct { | ||
AddAddresses []types.Address `json:"addAddress,omitempty"` | ||
RemoveAddresses []types.Address `json:"removeAddress,omitempty"` | ||
Whitelist []types.Address `json:"whitelist"` | ||
} | ||
|
||
func (r *DeploymentResult) GetOutput() string { | ||
var buffer bytes.Buffer | ||
|
||
buffer.WriteString("\n[CONTRACT DEPLOYMENT WHITELIST]\n\n") | ||
|
||
if len(r.AddAddresses) != 0 { | ||
buffer.WriteString(fmt.Sprintf("Added addresses: %s,\n", r.AddAddresses)) | ||
} | ||
|
||
if len(r.RemoveAddresses) != 0 { | ||
buffer.WriteString(fmt.Sprintf("Removed addresses: %s,\n", r.RemoveAddresses)) | ||
} | ||
|
||
buffer.WriteString(fmt.Sprintf("Contract deployment whitelist : %s,\n", r.Whitelist)) | ||
|
||
return buffer.String() | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
package show | ||
|
||
import ( | ||
"fmt" | ||
|
||
"github.com/0xPolygon/polygon-edge/chain" | ||
"github.com/0xPolygon/polygon-edge/command" | ||
"github.com/0xPolygon/polygon-edge/helper/config" | ||
"github.com/0xPolygon/polygon-edge/types" | ||
) | ||
|
||
const ( | ||
chainFlag = "chain" | ||
) | ||
|
||
var ( | ||
params = &showParams{} | ||
) | ||
|
||
type showParams struct { | ||
// genesis file path | ||
genesisPath string | ||
|
||
// deployment whitelist | ||
whitelists Whitelists | ||
} | ||
|
||
type Whitelists struct { | ||
deployment []types.Address | ||
} | ||
|
||
func (p *showParams) initRawParams() error { | ||
// init genesis configuration | ||
if err := p.initWhitelists(); err != nil { | ||
return err | ||
} | ||
|
||
return nil | ||
} | ||
|
||
func (p *showParams) initWhitelists() error { | ||
// import genesis configuration | ||
genesisConfig, err := chain.Import(p.genesisPath) | ||
if err != nil { | ||
return fmt.Errorf( | ||
"failed to load chain config from %s: %w", | ||
p.genesisPath, | ||
err, | ||
) | ||
} | ||
|
||
// fetch whitelists | ||
deploymentWhitelist, err := config.GetDeploymentWhitelist(genesisConfig) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
// set whitelists | ||
p.whitelists = Whitelists{ | ||
deployment: deploymentWhitelist, | ||
} | ||
|
||
return nil | ||
} | ||
|
||
func (p *showParams) getResult() command.CommandResult { | ||
result := &ShowResult{ | ||
Whitelists: p.whitelists, | ||
} | ||
|
||
return result | ||
} |
Oops, something went wrong.