mirror of https://github.com/certusone/wasmd.git
156 lines
4.5 KiB
Go
156 lines
4.5 KiB
Go
//go:build system_test && linux
|
|
|
|
package system
|
|
|
|
import (
|
|
"archive/tar"
|
|
"compress/gzip"
|
|
"fmt"
|
|
"io"
|
|
"net/http"
|
|
"os"
|
|
"path/filepath"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
"github.com/tidwall/gjson"
|
|
)
|
|
|
|
func TestChainUpgrade(t *testing.T) {
|
|
// Scenario:
|
|
// start a legacy chain with some state
|
|
// when a chain upgrade proposal is executed
|
|
// then the chain upgrades successfully
|
|
|
|
legacyBinary := FetchExecutable(t, "v0.41.0")
|
|
t.Logf("+++ legacy binary: %s\n", legacyBinary)
|
|
currentBranchBinary := sut.ExecBinary
|
|
sut.ExecBinary = legacyBinary
|
|
sut.SetupChain()
|
|
votingPeriod := 5 * time.Second // enough time to vote
|
|
sut.ModifyGenesisJSON(t, SetGovVotingPeriod(t, votingPeriod))
|
|
|
|
const (
|
|
upgradeHeight int64 = 22
|
|
upgradeName = "v0.50"
|
|
)
|
|
|
|
sut.StartChain(t, fmt.Sprintf("--halt-height=%d", upgradeHeight))
|
|
|
|
cli := NewWasmdCLI(t, sut, verbose)
|
|
|
|
// set some state to ensure that migrations work
|
|
verifierAddr := cli.AddKey("verifier")
|
|
beneficiary := randomBech32Addr()
|
|
cli.FundAddress(verifierAddr, "1000stake")
|
|
|
|
t.Log("Launch hackatom contract")
|
|
codeID := cli.WasmStore("./testdata/hackatom.wasm.gzip")
|
|
initMsg := fmt.Sprintf(`{"verifier":%q, "beneficiary":%q}`, verifierAddr, beneficiary)
|
|
contractAddr := cli.WasmInstantiate(codeID, initMsg, "--admin="+defaultSrcAddr, "--label=label1", "--from="+defaultSrcAddr, "--amount=1000000stake")
|
|
|
|
gotRsp := cli.QuerySmart(contractAddr, `{"verifier":{}}`)
|
|
require.Equal(t, fmt.Sprintf(`{"data":{"verifier":"%s"}}`, verifierAddr), gotRsp)
|
|
|
|
// submit upgrade proposal
|
|
proposal := fmt.Sprintf(`
|
|
{
|
|
"messages": [
|
|
{
|
|
"@type": "/cosmos.upgrade.v1beta1.MsgSoftwareUpgrade",
|
|
"authority": "wasm10d07y265gmmuvt4z0w9aw880jnsr700js7zslc",
|
|
"plan": {
|
|
"name": %q,
|
|
"height": "%d"
|
|
}
|
|
}
|
|
],
|
|
"metadata": "ipfs://CID",
|
|
"deposit": "100000000stake",
|
|
"title": "my upgrade",
|
|
"summary": "testing"
|
|
}`, upgradeName, upgradeHeight)
|
|
proposalID := cli.SubmitAndVoteGovProposal(proposal)
|
|
t.Logf("current_height: %d\n", sut.currentHeight)
|
|
raw := cli.CustomQuery("q", "gov", "proposal", proposalID)
|
|
t.Log(raw)
|
|
sut.AwaitBlockHeight(t, upgradeHeight-1)
|
|
t.Logf("current_height: %d\n", sut.currentHeight)
|
|
raw = cli.CustomQuery("q", "gov", "proposal", proposalID)
|
|
proposalStatus := gjson.Get(raw, "status").String()
|
|
require.Equal(t, "PROPOSAL_STATUS_PASSED", proposalStatus, raw)
|
|
|
|
t.Log("waiting for upgrade info")
|
|
sut.AwaitUpgradeInfo(t)
|
|
sut.StopChain()
|
|
|
|
t.Log("Upgrade height was reached. Upgrading chain")
|
|
sut.ExecBinary = currentBranchBinary
|
|
sut.StartChain(t)
|
|
cli = NewWasmdCLI(t, sut, verbose)
|
|
|
|
// ensure that state matches expectations
|
|
gotRsp = cli.QuerySmart(contractAddr, `{"verifier":{}}`)
|
|
require.Equal(t, fmt.Sprintf(`{"data":{"verifier":"%s"}}`, verifierAddr), gotRsp)
|
|
// and contract execution works as expected
|
|
RequireTxSuccess(t, cli.WasmExecute(contractAddr, `{"release":{}}`, verifierAddr))
|
|
assert.Equal(t, int64(1_000_000), cli.QueryBalance(beneficiary, "stake"))
|
|
}
|
|
|
|
const cacheDir = "binaries"
|
|
|
|
// FetchExecutable to download and extract tar.gz for linux
|
|
func FetchExecutable(t *testing.T, version string) string {
|
|
// use local cache
|
|
cacheFolder := filepath.Join(WorkDir, cacheDir)
|
|
err := os.MkdirAll(cacheFolder, 0o777)
|
|
if err != nil && !os.IsExist(err) {
|
|
panic(err)
|
|
}
|
|
|
|
cacheFile := filepath.Join(cacheFolder, fmt.Sprintf("%s_%s", execBinaryName, version))
|
|
if _, err := os.Stat(cacheFile); err == nil {
|
|
return cacheFile
|
|
}
|
|
t.Logf("+++ version not in cache, downloading from github")
|
|
|
|
// then download from GH releases: only works with Linux currently as we are not publishing OSX binaries
|
|
const releaseUrl = "https://github.com/CosmWasm/wasmd/releases/download/%s/wasmd-%s-linux-amd64.tar.gz"
|
|
destDir := t.TempDir()
|
|
rsp, err := http.Get(fmt.Sprintf(releaseUrl, version, version))
|
|
require.NoError(t, err)
|
|
defer rsp.Body.Close()
|
|
gzr, err := gzip.NewReader(rsp.Body)
|
|
require.NoError(t, err)
|
|
defer gzr.Close()
|
|
tr := tar.NewReader(gzr)
|
|
|
|
var workFileName string
|
|
for {
|
|
header, err := tr.Next()
|
|
switch {
|
|
case err == io.EOF:
|
|
require.NotEmpty(t, workFileName)
|
|
require.NoError(t, os.Rename(workFileName, cacheFile))
|
|
return cacheFile
|
|
case err != nil:
|
|
require.NoError(t, err)
|
|
case header == nil:
|
|
continue
|
|
}
|
|
workFileName = filepath.Join(destDir, header.Name)
|
|
switch header.Typeflag {
|
|
case tar.TypeDir:
|
|
t.Fatalf("unexpected type")
|
|
case tar.TypeReg:
|
|
f, err := os.OpenFile(workFileName, os.O_CREATE|os.O_RDWR, os.FileMode(0o755))
|
|
require.NoError(t, err)
|
|
_, err = io.Copy(f, tr)
|
|
require.NoError(t, err)
|
|
_ = f.Close()
|
|
}
|
|
}
|
|
}
|