// (c) 2019-2020, Ava Labs, Inc. All rights reserved.
// See the file LICENSE for licensing terms.
package evm
import (
"encoding/json"
"testing"
"github.com/ava-labs/avalanchego/api/keystore"
"github.com/ava-labs/avalanchego/chains/atomic"
"github.com/ava-labs/avalanchego/database/memdb"
"github.com/ava-labs/avalanchego/database/prefixdb"
"github.com/ava-labs/avalanchego/ids"
"github.com/ava-labs/avalanchego/snow"
engCommon "github.com/ava-labs/avalanchego/snow/engine/common"
"github.com/ava-labs/avalanchego/utils/crypto"
"github.com/ava-labs/avalanchego/utils/formatting"
"github.com/ava-labs/avalanchego/utils/logging"
"github.com/ava-labs/coreth/core"
"github.com/ethereum/go-ethereum/common"
)
var (
testNetworkID uint32 = 10
testCChainID = ids.ID([32]byte{'c', 'c', 'h', 'a', 'i', 'n', 't', 'e', 's', 't'})
testXChainID = ids.ID([32]byte{'t', 'e', 's', 't', 'x'})
nonExistentID = ids.ID([32]byte{'F'})
testTxFee = uint64(1000)
testKeys []*crypto.PrivateKeySECP256K1R
testEthAddrs []common.Address // testEthAddrs[i] corresponds to testKeys[i]
testShortIDAddrs []ids.ShortID
testAvaxAssetID = [32]byte{1, 2, 3}
username = "Johns"
password = "CjasdjhiPeirbSenfeI13" // #nosec G101
)
func init() {
cb58 := formatting.CB58{}
factory := crypto.FactorySECP256K1R{}
for _, key := range []string{
"24jUJ9vZexUM6expyMcT48LBx27k1m7xpraoV62oSQAHdziao5",
"2MMvUMsxx6zsHSNXJdFD8yc5XkancvwyKPwpw4xUK3TCGDuNBY",
"cxb7KpGWhDMALTjNNSJ7UQkkomPesyWAPUaWRGdyeBNzR6f35",
} {
_ = cb58.FromString(key)
pk, _ := factory.ToPrivateKey(cb58.Bytes)
secpKey := pk.(*crypto.PrivateKeySECP256K1R)
testKeys = append(testKeys, secpKey)
testEthAddrs = append(testEthAddrs, GetEthAddress(secpKey))
testShortIDAddrs = append(testShortIDAddrs, pk.PublicKey().Address())
}
}
// BuildGenesisTest returns the genesis bytes for Coreth VM to be used in testing
func BuildGenesisTest(t *testing.T) []byte {
ss := StaticService{}
genesisJSON := "{\"config\":{\"chainId\":43112,\"homesteadBlock\":0,\"daoForkBlock\":0,\"daoForkSupport\":true,\"eip150Block\":0,\"eip150Hash\":\"0x2086799aeebeae135c246c65021c82b4e15a2c451340993aacfd2751886514f0\",\"eip155Block\":0,\"eip158Block\":0,\"byzantiumBlock\":0,\"constantinopleBlock\":0,\"petersburgBlock\":0,\"istanbulBlock\":0,\"muirGlacierBlock\":0},\"nonce\":\"0x0\",\"timestamp\":\"0x0\",\"extraData\":\"0x00\",\"gasLimit\":\"0x5f5e100\",\"difficulty\":\"0x0\",\"mixHash\":\"0x0000000000000000000000000000000000000000000000000000000000000000\",\"coinbase\":\"0x0000000000000000000000000000000000000000\",\"alloc\":{\"0100000000000000000000000000000000000000\":{\"code\":\"0x7300000000000000000000000000000000000000003014608060405260043610603d5760003560e01c80631e010439146042578063b6510bb314606e575b600080fd5b605c60048036036020811015605657600080fd5b503560b1565b60408051918252519081900360200190f35b818015607957600080fd5b5060af60048036036080811015608e57600080fd5b506001600160a01b03813516906020810135906040810135906060013560b6565b005b30cd90565b836001600160a01b031681836108fc8690811502906040516000604051808303818888878c8acf9550505050505015801560f4573d6000803e3d6000fd5b505050505056fea26469706673582212201eebce970fe3f5cb96bf8ac6ba5f5c133fc2908ae3dcd51082cfee8f583429d064736f6c634300060a0033\",\"balance\":\"0x0\"}},\"number\":\"0x0\",\"gasUsed\":\"0x0\",\"parentHash\":\"0x0000000000000000000000000000000000000000000000000000000000000000\"}"
genesis := &core.Genesis{}
if err := json.Unmarshal([]byte(genesisJSON), genesis); err != nil {
t.Fatalf("Problem unmarshaling genesis JSON: %s", err)
}
genesisReply, err := ss.BuildGenesis(nil, genesis)
if err != nil {
t.Fatalf("Failed to create test genesis")
}
return genesisReply.Bytes
}
func NewContext() *snow.Context {
ctx := snow.DefaultContextTest()
ctx.NetworkID = testNetworkID
ctx.ChainID = testCChainID
ctx.AVAXAssetID = testAvaxAssetID
ctx.XChainID = ids.Empty.Prefix(0)
aliaser := ctx.BCLookup.(*ids.Aliaser)
_ = aliaser.Alias(testCChainID, "C")
_ = aliaser.Alias(testCChainID, testCChainID.String())
_ = aliaser.Alias(testXChainID, "X")
_ = aliaser.Alias(testXChainID, testXChainID.String())
// SNLookup might be required here???
return ctx
}
// GenesisVM creates a VM instance with the genesis test bytes and returns
// the channel use to send messages to the engine, the vm, and atomic memory
func GenesisVM(t *testing.T, finishBootstrapping bool) (chan engCommon.Message, *VM, []byte, *atomic.Memory) {
genesisBytes := BuildGenesisTest(t)
ctx := NewContext()
baseDB := memdb.New()
m := &atomic.Memory{}
m.Initialize(logging.NoLog{}, prefixdb.New([]byte{0}, baseDB))
ctx.SharedMemory = m.NewSharedMemory(ctx.ChainID)
// NB: this lock is intentionally left locked when this function returns.
// The caller of this function is responsible for unlocking.
ctx.Lock.Lock()
userKeystore := keystore.CreateTestKeystore()
if err := userKeystore.AddUser(username, password); err != nil {
t.Fatal(err)
}
ctx.Keystore = userKeystore.NewBlockchainKeyStore(ctx.ChainID)
issuer := make(chan engCommon.Message, 1)
vm := &VM{
txFee: testTxFee,
}
err := vm.Initialize(
ctx,
prefixdb.New([]byte{1}, baseDB),
genesisBytes,
issuer,
[]*engCommon.Fx{},
)
if err != nil {
t.Fatal(err)
}
return issuer, vm, genesisBytes, m
}
func TestVMGenesis(t *testing.T) {
_, _, _, _ = GenesisVM(t, true)
}