Skip to content

Commit

Permalink
sync upstream v0.5.2 (9a1c548)
Browse files Browse the repository at this point in the history
  • Loading branch information
atvanguard committed Jun 28, 2023
2 parents 2ba429b + 9a1c548 commit b0d09f2
Show file tree
Hide file tree
Showing 92 changed files with 10,929 additions and 43,130 deletions.
7 changes: 4 additions & 3 deletions .github/CODEOWNERS
Validating CODEOWNERS rules …
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

# Specific directories:

peer/ @anusha-ctrl
contract-examples/ @anusha-ctrl
scripts/ @anusha-ctrl
peer/ @anusha-ctrl @ceyonur @darioush @aaronbuchwald
contracts/ @anusha-ctrl @ceyonur @darioush @aaronbuchwald
scripts/ @anusha-ctrl @ceyonur @darioush @aaronbuchwald

8 changes: 4 additions & 4 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -68,10 +68,10 @@ jobs:
- name: Use Node.js
uses: actions/setup-node@v3
with:
node-version: "14.x"
- name: Yarn install
run: yarn
working-directory: ./contract-examples
node-version: "18.x"
- name: NPM Clean Install
run: npm ci
working-directory: ./contracts
- name: Install AvalancheGo Release
shell: bash
run: BASEDIR=/tmp/e2e-test AVALANCHEGO_BUILD_PATH=/tmp/e2e-test/avalanchego ./scripts/install_avalanchego_release.sh
Expand Down
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ var privateKey2 = "31b571bf6894a248831ff937bb49f7754509fe93bbd2517c9c73c4144c0e9
Each blockchain is an instance of a Virtual Machine (VM), much like an object in an object-oriented language is an instance of a class.
That is, the VM defines the behavior of the blockchain.

Subnet EVM is the [Virtual Machine (VM)](https://docs.avax.network/overview/getting-started/avalanche-platform/#virtual-machines) that defines the Subnet Contract Chains. Subnet EVM is a simplified version of [Coreth VM (C-Chain)](https://github.com/ava-labs/coreth).
Subnet EVM is the [Virtual Machine (VM)](https://docs.avax.network/learn/avalanche/virtual-machines) that defines the Subnet Contract Chains. Subnet EVM is a simplified version of [Coreth VM (C-Chain)](https://github.com/ava-labs/coreth).

This chain implements the Ethereum Virtual Machine and supports Solidity smart contracts as well as most other Ethereum client functionality.

Expand Down Expand Up @@ -59,7 +59,8 @@ The Subnet EVM runs in a separate process from the main AvalancheGo process and
[v0.4.11] [email protected] (Protocol Version: 24)
[v0.4.12] [email protected] (Protocol Version: 24)
[v0.5.0] [email protected] (Protocol Version: 25)
[v0.5.1] [email protected] (Protocol Version: 26)
[v0.5.1] [email protected] (Protocol Version: 26)
[v0.5.2] [email protected] (Protocol Version: 26)
```

## API
Expand Down
212 changes: 117 additions & 95 deletions accounts/abi/bind/precompilebind/precompile_contract_test_template.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,109 +23,112 @@ import (
"github.com/stretchr/testify/require"
)
// TestRun tests the Run function of the precompile contract.
// These tests are run against the precompile contract directly with
// the given input and expected output. They're just a guide to
// help you write your own tests. These tests are for general cases like
// allowlist, readOnly behaviour, and gas cost. You should write your own
// tests for specific cases.
func TestRun(t *testing.T) {
tests := map[string]testutils.PrecompileTest{
{{- $contract := .Contract}}
{{- $structs := .Structs}}
{{- range .Contract.Funcs}}
{{- $func := .}}
{{- if $contract.AllowList}}
{{- $roles := mkList "NoRole" "Enabled" "Admin"}}
{{- range $role := $roles}}
{{- $fail := and (not $func.Original.IsConstant) (eq $role "NoRole")}}
"calling {{decapitalise $func.Normalized.Name}} from {{$role}} should {{- if $fail}} fail {{- else}} succeed{{- end}}": {
Caller: allowlist.Test{{$role}}Addr,
BeforeHook: allowlist.SetDefaultRoles(Module.Address),
InputFn: func(t testing.TB) []byte {
{{- if len $func.Normalized.Inputs | lt 1}}
// These tests are run against the precompile contract directly with
// the given input and expected output. They're just a guide to
// help you write your own tests. These tests are for general cases like
// allowlist, readOnly behaviour, and gas cost. You should write your own
// tests for specific cases.
var(
tests = map[string]testutils.PrecompileTest{
{{- $contract := .Contract}}
{{- $structs := .Structs}}
{{- range .Contract.Funcs}}
{{- $func := .}}
{{- if $contract.AllowList}}
{{- $roles := mkList "NoRole" "Enabled" "Admin"}}
{{- range $role := $roles}}
{{- $fail := and (not $func.Original.IsConstant) (eq $role "NoRole")}}
"calling {{decapitalise $func.Normalized.Name}} from {{$role}} should {{- if $fail}} fail {{- else}} succeed{{- end}}": {
Caller: allowlist.Test{{$role}}Addr,
BeforeHook: allowlist.SetDefaultRoles(Module.Address),
InputFn: func(t testing.TB) []byte {
{{- if len $func.Normalized.Inputs | lt 1}}
// CUSTOM CODE STARTS HERE
// populate test input here
testInput := {{capitalise $func.Normalized.Name}}Input{}
input, err := Pack{{$func.Normalized.Name}}(testInput)
{{- else if len $func.Normalized.Inputs | eq 1 }}
{{- $input := index $func.Normalized.Inputs 0}}
// CUSTOM CODE STARTS HERE
// set test input to a value here
var testInput {{bindtype $input.Type $structs}}
input, err := Pack{{$func.Normalized.Name}}(testInput)
{{- else}}
input, err := Pack{{$func.Normalized.Name}}()
{{- end}}
require.NoError(t, err)
return input
},
{{- if not $fail}}
// This test is for a successful call. You can set the expected output here.
// CUSTOM CODE STARTS HERE
// populate test input here
testInput := {{capitalise $func.Normalized.Name}}Input{}
input, err := Pack{{$func.Normalized.Name}}(testInput)
{{- else if len $func.Normalized.Inputs | eq 1 }}
{{- $input := index $func.Normalized.Inputs 0}}
// CUSTOM CODE STARTS HERE
// set test input to a value here
var testInput {{bindtype $input.Type $structs}}
input, err := Pack{{$func.Normalized.Name}}(testInput)
{{- else}}
input, err := Pack{{$func.Normalized.Name}}()
ExpectedRes: []byte{},
{{- end}}
require.NoError(t, err)
return input
SuppliedGas: {{$func.Normalized.Name}}GasCost,
ReadOnly: false,
ExpectedErr: {{if $fail}} ErrCannot{{$func.Normalized.Name}}.Error() {{- else}} "" {{- end}},
},
{{- if not $fail}}
// This test is for a successful call. You can set the expected output here.
// CUSTOM CODE STARTS HERE
ExpectedRes: []byte{},
{{- end}}
SuppliedGas: {{$func.Normalized.Name}}GasCost,
ReadOnly: false,
ExpectedErr: {{if $fail}} ErrCannot{{$func.Normalized.Name}}.Error() {{- else}} "" {{- end}},
},
{{- end}}
{{- end}}
{{- if not $func.Original.IsConstant}}
"readOnly {{decapitalise $func.Normalized.Name}} should fail": {
Caller: common.Address{1},
InputFn: func(t testing.TB) []byte {
{{- if len $func.Normalized.Inputs | lt 1}}
// CUSTOM CODE STARTS HERE
// populate test input here
testInput := {{capitalise $func.Normalized.Name}}Input{}
input, err := Pack{{$func.Normalized.Name}}(testInput)
{{- else if len $func.Normalized.Inputs | eq 1 }}
{{- $input := index $func.Normalized.Inputs 0}}
// CUSTOM CODE STARTS HERE
// set test input to a value here
var testInput {{bindtype $input.Type $structs}}
input, err := Pack{{$func.Normalized.Name}}(testInput)
{{- else}}
input, err := Pack{{$func.Normalized.Name}}()
{{- end}}
require.NoError(t, err)
return input
{{- end}}
{{- if not $func.Original.IsConstant}}
"readOnly {{decapitalise $func.Normalized.Name}} should fail": {
Caller: common.Address{1},
InputFn: func(t testing.TB) []byte {
{{- if len $func.Normalized.Inputs | lt 1}}
// CUSTOM CODE STARTS HERE
// populate test input here
testInput := {{capitalise $func.Normalized.Name}}Input{}
input, err := Pack{{$func.Normalized.Name}}(testInput)
{{- else if len $func.Normalized.Inputs | eq 1 }}
{{- $input := index $func.Normalized.Inputs 0}}
// CUSTOM CODE STARTS HERE
// set test input to a value here
var testInput {{bindtype $input.Type $structs}}
input, err := Pack{{$func.Normalized.Name}}(testInput)
{{- else}}
input, err := Pack{{$func.Normalized.Name}}()
{{- end}}
require.NoError(t, err)
return input
},
SuppliedGas: {{$func.Normalized.Name}}GasCost,
ReadOnly: true,
ExpectedErr: vmerrs.ErrWriteProtection.Error(),
},
SuppliedGas: {{$func.Normalized.Name}}GasCost,
ReadOnly: true,
ExpectedErr: vmerrs.ErrWriteProtection.Error(),
},
{{- end}}
"insufficient gas for {{decapitalise $func.Normalized.Name}} should fail": {
Caller: common.Address{1},
InputFn: func(t testing.TB) []byte {
{{- if len $func.Normalized.Inputs | lt 1}}
// CUSTOM CODE STARTS HERE
// populate test input here
testInput := {{capitalise $func.Normalized.Name}}Input{}
input, err := Pack{{$func.Normalized.Name}}(testInput)
{{- else if len $func.Normalized.Inputs | eq 1 }}
{{- $input := index $func.Normalized.Inputs 0}}
// CUSTOM CODE STARTS HERE
// set test input to a value here
var testInput {{bindtype $input.Type $structs}}
input, err := Pack{{$func.Normalized.Name}}(testInput)
{{- else}}
input, err := Pack{{$func.Normalized.Name}}()
{{- end}}
require.NoError(t, err)
return input
{{- end}}
"insufficient gas for {{decapitalise $func.Normalized.Name}} should fail": {
Caller: common.Address{1},
InputFn: func(t testing.TB) []byte {
{{- if len $func.Normalized.Inputs | lt 1}}
// CUSTOM CODE STARTS HERE
// populate test input here
testInput := {{capitalise $func.Normalized.Name}}Input{}
input, err := Pack{{$func.Normalized.Name}}(testInput)
{{- else if len $func.Normalized.Inputs | eq 1 }}
{{- $input := index $func.Normalized.Inputs 0}}
// CUSTOM CODE STARTS HERE
// set test input to a value here
var testInput {{bindtype $input.Type $structs}}
input, err := Pack{{$func.Normalized.Name}}(testInput)
{{- else}}
input, err := Pack{{$func.Normalized.Name}}()
{{- end}}
require.NoError(t, err)
return input
},
SuppliedGas: {{$func.Normalized.Name}}GasCost - 1,
ReadOnly: false,
ExpectedErr: vmerrs.ErrOutOfGas.Error(),
},
SuppliedGas: {{$func.Normalized.Name}}GasCost - 1,
ReadOnly: false,
ExpectedErr: vmerrs.ErrOutOfGas.Error(),
},
{{- end}}
}
{{- end}}
}
)
// Test{{.Contract.Type}}Run tests the Run function of the precompile contract.
func Test{{.Contract.Type}}Run(t *testing.T) {
{{- if .Contract.AllowList}}
// Run tests with allowlist tests.
// This adds allowlist run tests to your custom tests
// This adds allowlist tests to your custom tests
// and runs them all together.
// Even if you don't add any custom tests, keep this. This will still
// run the default allowlist tests.
Expand All @@ -139,4 +142,23 @@ func TestRun(t *testing.T) {
}
{{- end}}
}
func Benchmark{{.Contract.Type}}(b *testing.B) {
{{- if .Contract.AllowList}}
// Benchmark tests with allowlist tests.
// This adds allowlist tests to your custom tests
// and benchmarks them all together.
// Even if you don't add any custom tests, keep this. This will still
// run the default allowlist tests.
allowlist.BenchPrecompileWithAllowList(b, Module, state.NewTestStateDB, tests)
{{- else}}
// Benchmark tests.
for name, test := range tests {
b.Run(name, func(b *testing.B) {
test.Bench(b, module, newStateDB(b))
})
}
{{- end}}
}
`
11 changes: 6 additions & 5 deletions cmd/precompilegen/template-readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,9 @@ Modifying code outside of these areas should be done with caution and with a dee
6- Add your config unit tests under generated package config_test.go
7- Add your contract unit tests under generated package contract_test.go
8- Additionally you can add a full-fledged VM test for your precompile under plugin/vm/vm_test.go. See existing precompile tests for examples.
9- Add your solidity interface and test contract to contract-examples/contracts
10- Write solidity tests for your precompile in contract-examples/test
11- Create your genesis with your precompile enabled in tests/precompile/genesis/
12- Create e2e test for your solidity test in tests/precompile/solidity/suites.go
13- Run your e2e precompile Solidity tests with './scripts/run_ginkgo.sh`
9- Add your solidity interface and test contract to contracts/contracts
10- Write solidity contract tests for your precompile in contracts/contracts/test
11- Write TypeScript DS-Test counterparts for your solidity tests in contracts/test
12- Create your genesis with your precompile enabled in tests/precompile/genesis/
13- Create e2e test for your solidity test in tests/precompile/solidity/suites.go
14- Run your e2e precompile Solidity tests with './scripts/run_ginkgo.sh`
8 changes: 4 additions & 4 deletions cmd/simulator/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,22 +35,22 @@ To start a single node network, follow the instructions from the AvalancheGo [RE
Once you've built AvalancheGo, open the AvalancheGo directory in a separate terminal window and run a single node non-staking network with the following command:

```bash
./build/avalanchego --staking-enabled=false --network-id=local
./build/avalanchego --sybil-protection-enabled=false --network-id=local
```

:::warning
WARNING:

The staking-enabled flag is only for local testing. Disabling staking serves two functions explicitly for testing purposes:

1. Ignore stake weight on the P-Chain and count each connected peer as having a stake weight of 1
2. Automatically opts in to validate every Subnet
:::

Once you have AvalancheGo running locally, it will be running an HTTP Server on the default port `9650`. This means that the RPC Endpoint for the C-Chain will be http://127.0.0.1:9650/ext/bc/C/rpc and ws://127.0.0.1:9650/ext/bc/C/ws for WebSocket connections.

Now, we can run the simulator command to simulate some load on the local C-Chain for 30s:

```bash
./simulator --timeout=1m --concurrency=1 --max-fee-cap=300 --max-tip-cap=10 --txs-per-worker=50
./simulator --timeout=1m --workers=1 --max-fee-cap=300 --max-tip-cap=10 --txs-per-worker=50
```

## Command Line Flags
Expand Down
4 changes: 4 additions & 0 deletions cmd/simulator/config/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ const (
KeyDirKey = "key-dir"
VersionKey = "version"
TimeoutKey = "timeout"
BatchSizeKey = "batch-size"
)

var (
Expand All @@ -42,6 +43,7 @@ type Config struct {
TxsPerWorker uint64 `json:"txs-per-worker"`
KeyDir string `json:"key-dir"`
Timeout time.Duration `json:"timeout"`
BatchSize uint64 `json:"batch-size"`
}

func BuildConfig(v *viper.Viper) (Config, error) {
Expand All @@ -53,6 +55,7 @@ func BuildConfig(v *viper.Viper) (Config, error) {
TxsPerWorker: v.GetUint64(TxsPerWorkerKey),
KeyDir: v.GetString(KeyDirKey),
Timeout: v.GetDuration(TimeoutKey),
BatchSize: v.GetUint64(BatchSizeKey),
}
if len(c.Endpoints) == 0 {
return c, ErrNoEndpoints
Expand Down Expand Up @@ -114,4 +117,5 @@ func addSimulatorFlags(fs *pflag.FlagSet) {
fs.String(KeyDirKey, ".simulator/keys", "Specify the directory to save private keys in (INSECURE: only use for testing)")
fs.Duration(TimeoutKey, 5*time.Minute, "Specify the timeout for the simulator to complete (0 indicates no timeout)")
fs.String(LogLevelKey, "info", "Specify the log level to use in the simulator")
fs.Uint64(BatchSizeKey, 100, "Specify the batchsize for the worker to issue and confirm txs")
}
16 changes: 9 additions & 7 deletions cmd/simulator/load/funder.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"math/big"

"github.com/ava-labs/subnet-evm/cmd/simulator/key"
"github.com/ava-labs/subnet-evm/cmd/simulator/txs"
"github.com/ava-labs/subnet-evm/core/types"
"github.com/ava-labs/subnet-evm/ethclient"
"github.com/ava-labs/subnet-evm/params"
Expand Down Expand Up @@ -80,7 +81,7 @@ func DistributeFunds(ctx context.Context, client ethclient.Client, keys []*key.K
signer := types.LatestSignerForChainID(chainID)

// Generate a sequence of transactions to distribute the required funds.
log.Info("Generating distribution transactions")
log.Info("Generating distribution transactions...")
i := 0
txGenerator := func(key *ecdsa.PrivateKey, nonce uint64) (*types.Transaction, error) {
tx, err := types.SignNewTx(key, signer, &types.DynamicFeeTx{
Expand All @@ -99,23 +100,24 @@ func DistributeFunds(ctx context.Context, client ethclient.Client, keys []*key.K
i++
return tx, nil
}
txs, err := GenerateTxSequence(ctx, txGenerator, client, maxFundsKey.PrivKey, uint64(len(needFundsAddrs)))

numTxs := uint64(len(needFundsAddrs))
txSequence, err := txs.GenerateTxSequence(ctx, txGenerator, client, maxFundsKey.PrivKey, numTxs)
if err != nil {
return nil, fmt.Errorf("failed to generate fund distribution sequence from %s of length %d", maxFundsKey.Address, len(needFundsAddrs))
}
worker := NewSingleAddressTxWorker(ctx, client, maxFundsKey.Address)
txFunderAgent := txs.NewIssueNAgent[*types.Transaction](txSequence, worker, numTxs)

log.Info("Executing distribution transactions...")
worker := NewWorker(client, maxFundsKey.Address, txs)
if err := worker.Execute(ctx); err != nil {
if err := txFunderAgent.Execute(ctx); err != nil {
return nil, err
}

for _, addr := range needFundsAddrs {
balance, err := client.BalanceAt(ctx, addr, nil)
if err != nil {
return nil, fmt.Errorf("failed to fetch balance for addr %s: %w", addr, err)
}
log.Info("Funded address has balance", "balance", balance)
log.Info("Funded address has balance", "addr", addr, "balance", balance)
}
fundedKeys = append(fundedKeys, needFundsKeys...)
return fundedKeys, nil
Expand Down
Loading

0 comments on commit b0d09f2

Please sign in to comment.