Skip to content

Commit

Permalink
chore: simulate a all zeroes public key without huge state trie
Browse files Browse the repository at this point in the history
  • Loading branch information
EclesioMeloJunior committed Oct 2, 2023
1 parent d13278e commit 59c29fa
Show file tree
Hide file tree
Showing 5 changed files with 129 additions and 82 deletions.
13 changes: 12 additions & 1 deletion lib/babe/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ var (
errInvalidMandatoryDispatch = errors.New("invalid mandatory dispatch")
errLookupFailed = errors.New("lookup failed")
errValidatorNotFound = errors.New("validator not found")
errBadSigner = errors.New("invalid signing address")
)

func newUnknownError(data scale.VaryingDataTypeValue) error {
Expand Down Expand Up @@ -271,6 +272,14 @@ func (MandatoryDispatch) Index() uint { return 9 }

func (MandatoryDispatch) String() string { return "mandatory dispatch" }

// MandatoryDispatch A transaction with a mandatory dispatch
type BadSigner struct{}

// Index returns VDT index
func (BadSigner) Index() uint { return 10 }

func (BadSigner) String() string { return "invalid signing address" }

func determineErrType(vdt scale.VaryingDataType) error {
vdtVal, err := vdt.Value()
if err != nil {
Expand Down Expand Up @@ -311,6 +320,8 @@ func determineErrType(vdt scale.VaryingDataType) error {
return &TransactionValidityError{errValidatorNotFound}
case UnknownCustom:
return &TransactionValidityError{newUnknownError(val)}
case BadSigner:
return &TransactionValidityError{errBadSigner}
}

return errInvalidResult
Expand All @@ -319,7 +330,7 @@ func determineErrType(vdt scale.VaryingDataType) error {
func determineErr(res []byte) error {
dispatchError := scale.MustNewVaryingDataType(other, CannotLookup{}, BadOrigin{}, Module{})
invalid := scale.MustNewVaryingDataType(Call{}, Payment{}, Future{}, Stale{}, BadProof{}, AncientBirthBlock{},
ExhaustsResources{}, invalidCustom, BadMandatory{}, MandatoryDispatch{})
ExhaustsResources{}, invalidCustom, BadMandatory{}, MandatoryDispatch{}, BadSigner{})
unknown := scale.MustNewVaryingDataType(ValidityCannotLookup{}, NoUnsignedValidator{}, unknownCustom)

okRes := scale.NewResult(nil, dispatchError)
Expand Down
6 changes: 6 additions & 0 deletions lib/runtime/constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,12 @@ const (
WESTEND_RUNTIME_V0929_FP = "westend_runtime-v929.compact.wasm"
WESTEND_RUNTIME_V0929_URL = "https://github.com/paritytech/polkadot/releases/download/v0.9." +
"29/westend_runtime-v9290.compact.compressed.wasm?raw=true"

// v0.9.12 westend used for zero-address bug
WESTEND_RUNTIME_v0912 = "westend_runtime-v9111"
WESTEND_RUNTIME_V0912_FP = "westend_runtime-v9111.compact.wasm"
WESTEND_RUNTIME_V0912_URL = "https://github.com/paritytech/polkadot/releases/download/v0.9." +
"11/westend_runtime-v9111.compact.compressed.wasm?raw=true"
)

const (
Expand Down
4 changes: 4 additions & 0 deletions lib/runtime/test_helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,10 @@ func GetRuntime(ctx context.Context, runtime string) (
case WESTEND_RUNTIME_v0929:
runtimeFilename = WESTEND_RUNTIME_V0929_FP
url = WESTEND_RUNTIME_V0929_URL
// only used for TestInstance_BadSignatureExtrinsic_On_WestendBlock8077850
case WESTEND_RUNTIME_v0912:
runtimeFilename = WESTEND_RUNTIME_V0912_FP
url = WESTEND_RUNTIME_V0912_URL
default:
return "", fmt.Errorf("%w: %s", ErrRuntimeUnknown, runtime)
}
Expand Down
1 change: 0 additions & 1 deletion lib/runtime/wazero/block8077850.yaml

This file was deleted.

187 changes: 107 additions & 80 deletions lib/runtime/wazero/instance_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,13 @@ package wazero_runtime
import (
_ "embed"

"archive/zip"
"bytes"
"encoding/json"
"io"
"math/big"
"os"
"path/filepath"
"testing"

"github.com/ChainSafe/gossamer/dot/network"
"github.com/ChainSafe/gossamer/dot/types"
"github.com/ChainSafe/gossamer/internal/log"
"github.com/ChainSafe/gossamer/lib/common"
Expand All @@ -28,15 +25,11 @@ import (
"github.com/ChainSafe/gossamer/lib/utils"
"github.com/ChainSafe/gossamer/pkg/scale"
"github.com/centrifuge/go-substrate-rpc-client/v4/signature"
"gopkg.in/yaml.v3"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

//go:embed block8077850.yaml
var block8077850 []byte

func mustHexTo64BArray(t *testing.T, inputHex string) (outputArray [64]byte) {
t.Helper()
copy(outputArray[:], common.MustHexToBytes(inputHex))
Expand Down Expand Up @@ -412,83 +405,133 @@ func TestInstance_BabeConfiguration_WestendRuntime_NoAuthorities(t *testing.T) {
require.Equal(t, expected, cfg)
}

func extractZippedState(t *testing.T, zippedFile, destPath string) {
r, err := zip.OpenReader(zippedFile)
require.NoError(t, err)
require.Equal(t, len(r.File), 1)
func TestInstance_BadSignature_WestendBlock8077850(t *testing.T) {
tests := map[string]struct {
setupRuntime func(t *testing.T) (*Instance, *types.Header)
expectedError []byte
}{
"westend_dev_runtime_should_fail_with_bad_signature": {
expectedError: []byte{1, 0, 0xa},
setupRuntime: func(t *testing.T) (*Instance, *types.Header) {
genesisPath := utils.GetWestendDevRawGenesisPath(t)
gen := genesisFromRawJSON(t, genesisPath)
genTrie, err := runtime.NewTrieFromGenesis(gen)
require.NoError(t, err)

f := r.File[0]
outFile, err := os.OpenFile(destPath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, f.Mode())
require.NoError(t, err)
//set state to genesis state
genState := storage.NewTrieState(&genTrie)

rc, err := f.Open()
require.NoError(t, err)
cfg := Config{
Storage: genState,
LogLvl: log.Critical,
}

_, err = io.CopyN(outFile, rc, rc)
require.NoError(t, err)
rt, err := NewRuntimeFromGenesis(cfg)
require.NoError(t, err)

t.Cleanup(func() {
require.NoError(t, outFile.Close())
require.NoError(t, rc.Close())
require.NoError(t, r.Close())
})
}
// reset state back to parent state before executing
parentState := storage.NewTrieState(&genTrie)
rt.SetContextStorage(parentState)

func TestInstance_ExecuteBlock_WestendRuntime_WestendBlock8077850(t *testing.T) {
stateTrieFile := t.TempDir() + "state_block8077850.txt"
extractZippedState(t, "../test_data/westend/state_block8077850.zip", stateTrieFile)
genesisHeader := &types.Header{
Number: 0,
StateRoot: genTrie.MustHash(),
}

gossTrie8077850 := newTrieFromScaledPairs(t, stateTrieFile)
expectedRoot := common.MustHexToHash("0x731cea81940165128e1ffdfc5b4207e2ad84548377899b392dc497b1c166dc1f")
header := &types.Header{
ParentHash: genesisHeader.Hash(),
Number: 1,
Digest: types.NewDigest(),
}

require.Equal(t, expectedRoot, gossTrie8077850.MustHash())
return rt, header
},
},
"westend_0912_runtime_should_fail_with_invalid_payment": {
expectedError: []byte{1, 0, 1},
setupRuntime: func(t *testing.T) (*Instance, *types.Header) {
genesisPath := utils.GetWestendDevRawGenesisPath(t)
gen := genesisFromRawJSON(t, genesisPath)
genTrie, err := runtime.NewTrieFromGenesis(gen)
require.NoError(t, err)

// set state to genesis state
state8077850 := storage.NewTrieState(gossTrie8077850)
cfg := Config{
Storage: state8077850,
LogLvl: log.Critical,
rt := NewTestInstance(t, runtime.WESTEND_RUNTIME_v0912)
parentState := storage.NewTrieState(&genTrie)
rt.SetContextStorage(parentState)

genesisHeader := &types.Header{
Number: 0,
StateRoot: genTrie.MustHash(),
}

header := &types.Header{
ParentHash: genesisHeader.Hash(),
Number: 1,
Digest: types.NewDigest(),
}

return rt, header
},
},
}

instance, err := NewInstanceFromTrie(gossTrie8077850, cfg)
require.NoError(t, err)
for tname, tt := range tests {
tt := tt

block8077850Data := struct {
BlockData string `yaml:"blockData"`
}{}
t.Run(tname, func(t *testing.T) {
instance, header := tt.setupRuntime(t)

err = yaml.NewDecoder(bytes.NewReader(block8077850)).Decode(&block8077850Data)
require.NoError(t, err)
err := instance.InitializeBlock(header)
require.NoError(t, err)

idata := types.NewInherentData()
err = idata.SetInherent(types.Timstap0, uint64(5))
require.NoError(t, err)

entireBlockData := common.MustHexToBytes(block8077850Data.BlockData)
err = idata.SetInherent(types.Babeslot, uint64(1))
require.NoError(t, err)

blockResponseData := new(network.BlockResponseMessage)
err = blockResponseData.Decode(entireBlockData)
require.NoError(t, err)
ienc, err := idata.Encode()
require.NoError(t, err)

block := &types.Block{
Header: *blockResponseData.BlockData[0].Header,
Body: *blockResponseData.BlockData[0].Body,
}
// Call BlockBuilder_inherent_extrinsics which returns the inherents as encoded extrinsics
inherentExts, err := instance.InherentExtrinsics(ienc)
require.NoError(t, err)

exts, err := block.Body.AsEncodedExtrinsics()
require.NoError(t, err)
// decode inherent extrinsics
cp := make([]byte, len(inherentExts))
copy(cp, inherentExts)
var inExts [][]byte
err = scale.Unmarshal(cp, &inExts)
require.NoError(t, err)

expectedExtrinsics := []string{
"0x8bea0528dc1e7b07896a36d6d2ecb86c6cccbda21064089b5212a081d8b62631",
"0xc0014ff921c3bf55333621237f3058af2d2a696bddf5f703338a7c3b11c1965f",
"0x41b93a99fee24501ddeb1cc2dcfbec938c99a3d94531c7e16b4f4e102a9df38a",
}
// apply each inherent extrinsic
for _, inherent := range inExts {
in, err := scale.Marshal(inherent)
require.NoError(t, err)

var bodyExtrinsicHashes []string
for _, ext := range exts {
bodyExtrinsicHashes = append(bodyExtrinsicHashes, ext.Hash().String())
}
ret, err := instance.ApplyExtrinsic(in)
require.NoError(t, err)
require.Equal(t, ret, []byte{0, 0})
}

require.Equal(t, expectedExtrinsics, bodyExtrinsicHashes)
keyring, err := signature.KeyringPairFromSecret(
"0x00000000000000000000000000000000000000000000000000000"+
"00000000000000000000000000000000000000000000000000000"+
"0000000000000000000000", 42)
require.NoError(t, err)

_, err = instance.ExecuteBlock(block)
require.NoError(t, err)
extHex := runtime.NewTestExtrinsic(t, instance, header.ParentHash, header.ParentHash,
0, keyring, "System.remark", []byte{0xab, 0xcd})

res, err := instance.ApplyExtrinsic(common.MustHexToBytes(extHex))
require.NoError(t, err)

// should fail with transaction validity error: invalid payment for runtime 0.9.12
// should fail with transaction validity error: bad signature for runtime version greater than 0.9.12
require.Equal(t, tt.expectedError, res)
})
}

}

Expand Down Expand Up @@ -1056,22 +1099,6 @@ func newTrieFromPairs(t *testing.T, filename string) *trie.Trie {
return &tr
}

func newTrieFromScaledPairs(t *testing.T, filename string) *trie.Trie {
data, err := os.ReadFile(filename)
require.NoError(t, err)

decoded := make([][2][]byte, 0)
err = scale.Unmarshal(data, &decoded)
require.NoError(t, err)

trie, err := trie.LoadFromEntries(decoded)
if err != nil {
panic(err)
}

return trie
}

func TestInstance_TransactionPaymentCallApi_QueryCallInfo(t *testing.T) {
ins := NewTestInstance(t, runtime.WESTEND_RUNTIME_v0929)
tests := []struct {
Expand Down

0 comments on commit 59c29fa

Please sign in to comment.