Exemplo n.º 1
0
// Tests that subsequent signers can be promoted, each requiring half plus one
// votes for it to pass through.
func TestSignerPromotion(t *testing.T) {
	// Prefund a few accounts to authorize with and create the oracle
	keys := make([]*ecdsa.PrivateKey, 5)
	for i := 0; i < len(keys); i++ {
		keys[i], _ = crypto.GenerateKey()
	}
	key, oracle, sim := setupReleaseTest(t, keys...)

	// Gradually promote the keys, until all are authorized
	keys = append([]*ecdsa.PrivateKey{key}, keys...)
	for i := 1; i < len(keys); i++ {
		// Check that no votes are accepted from the not yet authed user
		if _, err := oracle.Promote(bind.NewKeyedTransactor(keys[i]), common.Address{}); err != nil {
			t.Fatalf("Iter #%d: failed invalid promotion attempt: %v", i, err)
		}
		sim.Commit()

		pend, err := oracle.AuthProposals(nil)
		if err != nil {
			t.Fatalf("Iter #%d: failed to retrieve active proposals: %v", i, err)
		}
		if len(pend) != 0 {
			t.Fatalf("Iter #%d: proposal count mismatch: have %d, want 0", i, len(pend))
		}
		// Promote with half - 1 voters and check that the user's not yet authorized
		for j := 0; j < i/2; j++ {
			if _, err = oracle.Promote(bind.NewKeyedTransactor(keys[j]), crypto.PubkeyToAddress(keys[i].PublicKey)); err != nil {
				t.Fatalf("Iter #%d: failed valid promotion attempt: %v", i, err)
			}
		}
		sim.Commit()

		signers, err := oracle.Signers(nil)
		if err != nil {
			t.Fatalf("Iter #%d: failed to retrieve list of signers: %v", i, err)
		}
		if len(signers) != i {
			t.Fatalf("Iter #%d: signer count mismatch: have %v, want %v", i, len(signers), i)
		}
		// Promote with the last one needed to pass the promotion
		if _, err = oracle.Promote(bind.NewKeyedTransactor(keys[i/2]), crypto.PubkeyToAddress(keys[i].PublicKey)); err != nil {
			t.Fatalf("Iter #%d: failed valid promotion completion attempt: %v", i, err)
		}
		sim.Commit()

		signers, err = oracle.Signers(nil)
		if err != nil {
			t.Fatalf("Iter #%d: failed to retrieve list of signers: %v", i, err)
		}
		if len(signers) != i+1 {
			t.Fatalf("Iter #%d: signer count mismatch: have %v, want %v", i, len(signers), i+1)
		}
	}
}
Exemplo n.º 2
0
// Tests that proposed versions can be nuked out of existence.
func TestVersionNuking(t *testing.T) {
	// Prefund a few accounts to authorize with and create the oracle
	keys := make([]*ecdsa.PrivateKey, 9)
	for i := 0; i < len(keys); i++ {
		keys[i], _ = crypto.GenerateKey()
	}
	key, oracle, sim := setupReleaseTest(t, keys...)

	// Authorize all the keys as valid signers
	keys = append([]*ecdsa.PrivateKey{key}, keys...)
	for i := 1; i < len(keys); i++ {
		for j := 0; j <= i/2; j++ {
			if _, err := oracle.Promote(bind.NewKeyedTransactor(keys[j]), crypto.PubkeyToAddress(keys[i].PublicKey)); err != nil {
				t.Fatalf("Iter #%d: failed valid promotion attempt: %v", i, err)
			}
		}
		sim.Commit()
	}
	// Propose releases with more and more keys, always retaining enough users to nuke the proposals
	for i := 1; i < (len(keys)+1)/2; i++ {
		// Propose release with an initial set of signers
		for j := 0; j < i; j++ {
			if _, err := oracle.Release(bind.NewKeyedTransactor(keys[j]), uint32(i), uint32(i+1), uint32(i+2), [20]byte{byte(i + 3)}); err != nil {
				t.Fatalf("Iter #%d: failed valid proposal attempt: %v", i, err)
			}
		}
		sim.Commit()

		prop, err := oracle.ProposedVersion(nil)
		if err != nil {
			t.Fatalf("Iter #%d: failed to retrieve active proposal: %v", i, err)
		}
		if len(prop.Pass) != i {
			t.Fatalf("Iter #%d: proposal vote count mismatch: have %d, want %d", i, len(prop.Pass), i)
		}
		// Nuke the release with half+1 voters
		for j := i; j <= i+(len(keys)+1)/2; j++ {
			if _, err := oracle.Nuke(bind.NewKeyedTransactor(keys[j])); err != nil {
				t.Fatalf("Iter #%d: failed valid nuke attempt: %v", i, err)
			}
		}
		sim.Commit()

		prop, err = oracle.ProposedVersion(nil)
		if err != nil {
			t.Fatalf("Iter #%d: failed to retrieve active proposal: %v", i, err)
		}
		if len(prop.Pass) != 0 || len(prop.Fail) != 0 {
			t.Fatalf("Iter #%d: proposal vote count mismatch: have %d/%d pass/fail, want 0/0", i, len(prop.Pass), len(prop.Fail))
		}
	}
}
Exemplo n.º 3
0
// Tests that demoting a signer will auto-nuke the currently pending release.
func TestVersionAutoNuke(t *testing.T) {
	// Prefund a few accounts to authorize with and create the oracle
	keys := make([]*ecdsa.PrivateKey, 5)
	for i := 0; i < len(keys); i++ {
		keys[i], _ = crypto.GenerateKey()
	}
	key, oracle, sim := setupReleaseTest(t, keys...)

	// Authorize all the keys as valid signers
	keys = append([]*ecdsa.PrivateKey{key}, keys...)
	for i := 1; i < len(keys); i++ {
		for j := 0; j <= i/2; j++ {
			if _, err := oracle.Promote(bind.NewKeyedTransactor(keys[j]), crypto.PubkeyToAddress(keys[i].PublicKey)); err != nil {
				t.Fatalf("Iter #%d: failed valid promotion attempt: %v", i, err)
			}
		}
		sim.Commit()
	}
	// Make a release proposal and check it's existence
	if _, err := oracle.Release(bind.NewKeyedTransactor(keys[0]), 1, 2, 3, [20]byte{4}); err != nil {
		t.Fatalf("Failed valid proposal attempt: %v", err)
	}
	sim.Commit()

	prop, err := oracle.ProposedVersion(nil)
	if err != nil {
		t.Fatalf("Failed to retrieve active proposal: %v", err)
	}
	if len(prop.Pass) != 1 {
		t.Fatalf("Proposal vote count mismatch: have %d, want 1", len(prop.Pass))
	}
	// Demote a signer and check release proposal deletion
	for i := 0; i <= len(keys)/2; i++ {
		if _, err := oracle.Demote(bind.NewKeyedTransactor(keys[i]), crypto.PubkeyToAddress(keys[len(keys)-1].PublicKey)); err != nil {
			t.Fatalf("Iter #%d: failed valid demotion attempt: %v", i, err)
		}
	}
	sim.Commit()

	prop, err = oracle.ProposedVersion(nil)
	if err != nil {
		t.Fatalf("Failed to retrieve active proposal: %v", err)
	}
	if len(prop.Pass) != 0 {
		t.Fatalf("Proposal vote count mismatch: have %d, want 0", len(prop.Pass))
	}
}
Exemplo n.º 4
0
// setupReleaseTest creates a blockchain simulator and deploys a version oracle
// contract for testing.
func setupReleaseTest(t *testing.T, prefund ...*ecdsa.PrivateKey) (*ecdsa.PrivateKey, *ReleaseOracle, *backends.SimulatedBackend) {
	// Generate a new random account and a funded simulator
	key, _ := crypto.GenerateKey()
	auth := bind.NewKeyedTransactor(key)

	accounts := []core.GenesisAccount{{Address: auth.From, Balance: big.NewInt(10000000000)}}
	for _, key := range prefund {
		accounts = append(accounts, core.GenesisAccount{Address: crypto.PubkeyToAddress(key.PublicKey), Balance: big.NewInt(10000000000)})
	}
	sim := backends.NewSimulatedBackend(accounts...)

	// Deploy a version oracle contract, commit and return
	_, _, oracle, err := DeployReleaseOracle(auth, sim, []common.Address{auth.From})
	if err != nil {
		t.Fatalf("Failed to deploy version contract: %v", err)
	}
	sim.Commit()

	return key, oracle, sim
}
Exemplo n.º 5
0
func TestDeploymentAndIntegration(t *testing.T) {
	// generate new key
	key := crypto.NewKey(rand.Reader)
	// init new simulated backend
	sim := backends.NewSimulatedBackend(core.GenesisAccount{Address: key.Address, Balance: big.NewInt(10000000000)})

	// created authenticator
	auth := bind.NewKeyedTransactor(key)

	// deploy the contract
	_, _, api, err := DeployEtherAPIs(auth, sim)

	// use a session based approach so that we do not need
	// to repass these settings all the time.
	session := &EtherAPIsSession{
		Contract: api,
		CallOpts: bind.CallOpts{
			Pending: true,
		},
		TransactOpts: bind.TransactOpts{
			From:     auth.From,
			Signer:   auth.Signer,
			GasLimit: big.NewInt(400000),
		},
	}

	// add a new service
	_, err = session.AddService("etherapis", "https://etherapis.io", big.NewInt(0), big.NewInt(10), big.NewInt(432000))
	if err != nil {
		t.Error(err)
	}

	// retrieve the service
	service, err := session.GetService(big.NewInt(0))
	if err != nil {
		t.Fatal(err)
	}
	if service.Enabled {
		t.Error("expected service to be disabled")
	}

	// enable the service
	_, err = session.EnableService(big.NewInt(0))
	if err != nil {
		t.Fatal(err)
	}
	service, err = session.GetService(big.NewInt(0))
	if err != nil {
		t.Fatal(err)
	}
	if !service.Enabled {
		t.Error("expected service to be enabled")
	}

	// flag deletion
	_, err = session.DeleteService(big.NewInt(0))
	if err != nil {
		t.Fatal(err)
	}

	service, err = session.GetService(big.NewInt(0))
	if err != nil {
		t.Fatal(err)
	}
	if !service.Deleted {
		t.Error("expected service to be deleted")
	}
}
Exemplo n.º 6
0
// Tests that new versions can be released, honouring both voting rights as well
// as the minimum required vote count.
func TestVersionRelease(t *testing.T) {
	// Prefund a few accounts to authorize with and create the oracle
	keys := make([]*ecdsa.PrivateKey, 5)
	for i := 0; i < len(keys); i++ {
		keys[i], _ = crypto.GenerateKey()
	}
	key, oracle, sim := setupReleaseTest(t, keys...)

	// Track the "current release"
	var (
		verMajor  = uint32(0)
		verMinor  = uint32(0)
		verPatch  = uint32(0)
		verCommit = [20]byte{}
	)
	// Gradually push releases, always requiring more signers than previously
	keys = append([]*ecdsa.PrivateKey{key}, keys...)
	for i := 1; i < len(keys); i++ {
		// Check that no votes are accepted from the not yet authed user
		if _, err := oracle.Release(bind.NewKeyedTransactor(keys[i]), 0, 0, 0, [20]byte{0}); err != nil {
			t.Fatalf("Iter #%d: failed invalid release attempt: %v", i, err)
		}
		sim.Commit()

		prop, err := oracle.ProposedVersion(nil)
		if err != nil {
			t.Fatalf("Iter #%d: failed to retrieve active proposal: %v", i, err)
		}
		if len(prop.Pass) != 0 {
			t.Fatalf("Iter #%d: proposal vote count mismatch: have %d, want 0", i, len(prop.Pass))
		}
		// Authorize the user to make releases
		for j := 0; j <= i/2; j++ {
			if _, err = oracle.Promote(bind.NewKeyedTransactor(keys[j]), crypto.PubkeyToAddress(keys[i].PublicKey)); err != nil {
				t.Fatalf("Iter #%d: failed valid promotion attempt: %v", i, err)
			}
		}
		sim.Commit()

		// Propose release with half voters and check that the release does not yet go through
		for j := 0; j < (i+1)/2; j++ {
			if _, err = oracle.Release(bind.NewKeyedTransactor(keys[j]), uint32(i), uint32(i+1), uint32(i+2), [20]byte{byte(i + 3)}); err != nil {
				t.Fatalf("Iter #%d: failed valid release attempt: %v", i, err)
			}
		}
		sim.Commit()

		ver, err := oracle.CurrentVersion(nil)
		if err != nil {
			t.Fatalf("Iter #%d: failed to retrieve current version: %v", i, err)
		}
		if ver.Major != verMajor || ver.Minor != verMinor || ver.Patch != verPatch || ver.Commit != verCommit {
			t.Fatalf("Iter #%d: version mismatch: have %d.%d.%d-%x, want %d.%d.%d-%x", i, ver.Major, ver.Minor, ver.Patch, ver.Commit, verMajor, verMinor, verPatch, verCommit)
		}

		// Pass the release and check that it became the next version
		verMajor, verMinor, verPatch, verCommit = uint32(i), uint32(i+1), uint32(i+2), [20]byte{byte(i + 3)}
		if _, err = oracle.Release(bind.NewKeyedTransactor(keys[(i+1)/2]), uint32(i), uint32(i+1), uint32(i+2), [20]byte{byte(i + 3)}); err != nil {
			t.Fatalf("Iter #%d: failed valid release completion attempt: %v", i, err)
		}
		sim.Commit()

		ver, err = oracle.CurrentVersion(nil)
		if err != nil {
			t.Fatalf("Iter #%d: failed to retrieve current version: %v", i, err)
		}
		if ver.Major != verMajor || ver.Minor != verMinor || ver.Patch != verPatch || ver.Commit != verCommit {
			t.Fatalf("Iter #%d: version mismatch: have %d.%d.%d-%x, want %d.%d.%d-%x", i, ver.Major, ver.Minor, ver.Patch, ver.Commit, verMajor, verMinor, verPatch, verCommit)
		}
	}
}