Merge pull request #2453 from nspcc-dev/check-policy-for-committee-members
Check policy for committee members
This commit is contained in:
commit
10acdbe40e
5 changed files with 37 additions and 24 deletions
|
@ -77,19 +77,17 @@ func NewContracts(cfg config.ProtocolConfiguration) *Contracts {
|
|||
|
||||
gas := newGAS(int64(cfg.InitialGASSupply), cfg.P2PSigExtensions)
|
||||
neo := newNEO()
|
||||
policy := newPolicy()
|
||||
neo.GAS = gas
|
||||
neo.Policy = policy
|
||||
gas.NEO = neo
|
||||
mgmt.NEO = neo
|
||||
policy.NEO = neo
|
||||
|
||||
cs.GAS = gas
|
||||
cs.NEO = neo
|
||||
cs.Contracts = append(cs.Contracts, neo)
|
||||
cs.Contracts = append(cs.Contracts, gas)
|
||||
|
||||
policy := newPolicy()
|
||||
policy.NEO = neo
|
||||
cs.Policy = policy
|
||||
cs.Contracts = append(cs.Contracts, policy)
|
||||
cs.Contracts = append(cs.Contracts, neo, gas, policy)
|
||||
|
||||
desig := newDesignate(cfg.P2PSigExtensions)
|
||||
desig.NEO = neo
|
||||
|
|
|
@ -20,17 +20,20 @@ import (
|
|||
"github.com/nspcc-dev/neo-go/pkg/crypto/hash"
|
||||
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
||||
"github.com/nspcc-dev/neo-go/pkg/encoding/bigint"
|
||||
"github.com/nspcc-dev/neo-go/pkg/io"
|
||||
"github.com/nspcc-dev/neo-go/pkg/smartcontract"
|
||||
"github.com/nspcc-dev/neo-go/pkg/smartcontract/callflag"
|
||||
"github.com/nspcc-dev/neo-go/pkg/smartcontract/manifest"
|
||||
"github.com/nspcc-dev/neo-go/pkg/util"
|
||||
"github.com/nspcc-dev/neo-go/pkg/vm/emit"
|
||||
"github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
|
||||
)
|
||||
|
||||
// NEO represents NEO native contract.
|
||||
type NEO struct {
|
||||
nep17TokenNative
|
||||
GAS *GAS
|
||||
GAS *GAS
|
||||
Policy *Policy
|
||||
|
||||
// gasPerBlock represents current value of generated gas per block.
|
||||
// It is append-only and doesn't need to be copied when used.
|
||||
|
@ -822,11 +825,14 @@ func (n *NEO) ModifyAccountVotes(acc *state.NEOBalance, d *dao.Simple, value *bi
|
|||
|
||||
func (n *NEO) getCandidates(d *dao.Simple, sortByKey bool) ([]keyWithVotes, error) {
|
||||
arr := make([]keyWithVotes, 0)
|
||||
buf := io.NewBufBinWriter()
|
||||
d.Seek(n.ID, storage.SeekRange{Prefix: []byte{prefixCandidate}}, func(k, v []byte) bool {
|
||||
c := new(candidate).FromBytes(v)
|
||||
if c.Registered {
|
||||
emit.CheckSig(buf.BinWriter, k)
|
||||
if c.Registered && !n.Policy.IsBlockedInternal(d, hash.Hash160(buf.Bytes())) {
|
||||
arr = append(arr, keyWithVotes{Key: string(k), Votes: &c.Votes})
|
||||
}
|
||||
buf.Reset()
|
||||
return true
|
||||
})
|
||||
|
||||
|
|
|
@ -49,6 +49,7 @@ func TestNEO_RegisterPrice(t *testing.T) {
|
|||
func TestNEO_Vote(t *testing.T) {
|
||||
neoCommitteeInvoker := newNeoCommitteeClient(t, 100_0000_0000)
|
||||
neoValidatorsInvoker := neoCommitteeInvoker.WithSigners(neoCommitteeInvoker.Validator)
|
||||
policyInvoker := neoCommitteeInvoker.CommitteeInvoker(neoCommitteeInvoker.NativeHash(t, nativenames.Policy))
|
||||
e := neoCommitteeInvoker.Executor
|
||||
|
||||
cfg := e.Chain.GetConfig()
|
||||
|
@ -71,23 +72,23 @@ func TestNEO_Vote(t *testing.T) {
|
|||
|
||||
// voters vote for candidates. The aim of this test is to check that voting
|
||||
// reward is proportional to the NEO balance.
|
||||
voters := make([]neotest.Signer, committeeSize)
|
||||
voters := make([]neotest.Signer, committeeSize+1)
|
||||
// referenceAccounts perform the same actions as voters except voting, i.e. we
|
||||
// will transfer the same amount of NEO to referenceAccounts and see how much
|
||||
// GAS they receive for NEO ownership. We need these values to be able to define
|
||||
// how much GAS voters receive for NEO ownership.
|
||||
referenceAccounts := make([]neotest.Signer, committeeSize)
|
||||
candidates := make([]neotest.Signer, committeeSize)
|
||||
for i := 0; i < committeeSize; i++ {
|
||||
referenceAccounts := make([]neotest.Signer, committeeSize+1)
|
||||
candidates := make([]neotest.Signer, committeeSize+1)
|
||||
for i := 0; i < committeeSize+1; i++ {
|
||||
voters[i] = e.NewAccount(t, 10_0000_0000)
|
||||
referenceAccounts[i] = e.NewAccount(t, 10_0000_0000)
|
||||
candidates[i] = e.NewAccount(t, 2000_0000_0000) // enough for one registration
|
||||
}
|
||||
txes := make([]*transaction.Transaction, 0, committeeSize*4-2)
|
||||
for i := 0; i < committeeSize; i++ {
|
||||
transferTx := neoValidatorsInvoker.PrepareInvoke(t, "transfer", e.Validator.ScriptHash(), voters[i].(neotest.SingleSigner).Account().PrivateKey().GetScriptHash(), int64(committeeSize-i)*1000000, nil)
|
||||
for i := 0; i < committeeSize+1; i++ {
|
||||
transferTx := neoValidatorsInvoker.PrepareInvoke(t, "transfer", e.Validator.ScriptHash(), voters[i].(neotest.SingleSigner).Account().PrivateKey().GetScriptHash(), int64(committeeSize+1-i)*1000000, nil)
|
||||
txes = append(txes, transferTx)
|
||||
transferTx = neoValidatorsInvoker.PrepareInvoke(t, "transfer", e.Validator.ScriptHash(), referenceAccounts[i].(neotest.SingleSigner).Account().PrivateKey().GetScriptHash(), int64(committeeSize-i)*1000000, nil)
|
||||
transferTx = neoValidatorsInvoker.PrepareInvoke(t, "transfer", e.Validator.ScriptHash(), referenceAccounts[i].(neotest.SingleSigner).Account().PrivateKey().GetScriptHash(), int64(committeeSize+1-i)*1000000, nil)
|
||||
txes = append(txes, transferTx)
|
||||
if i > 0 {
|
||||
registerTx := neoValidatorsInvoker.WithSigners(candidates[i]).PrepareInvoke(t, "registerCandidate", candidates[i].(neotest.SingleSigner).Account().PrivateKey().PublicKey().Bytes())
|
||||
|
@ -96,6 +97,7 @@ func TestNEO_Vote(t *testing.T) {
|
|||
txes = append(txes, voteTx)
|
||||
}
|
||||
}
|
||||
txes = append(txes, policyInvoker.PrepareInvoke(t, "blockAccount", candidates[len(candidates)-1].(neotest.SingleSigner).Account().PrivateKey().PublicKey().GetScriptHash()))
|
||||
neoValidatorsInvoker.AddNewBlock(t, txes...)
|
||||
for _, tx := range txes {
|
||||
e.CheckHalt(t, tx.Hash(), stackitem.Make(true)) // luckily, both `transfer`, `registerCandidate` and `vote` return boolean values
|
||||
|
@ -137,12 +139,12 @@ func TestNEO_Vote(t *testing.T) {
|
|||
require.EqualValues(t, sortedCandidates, pubs)
|
||||
|
||||
t.Run("check voter rewards", func(t *testing.T) {
|
||||
gasBalance := make([]*big.Int, len(voters))
|
||||
referenceGASBalance := make([]*big.Int, len(referenceAccounts))
|
||||
neoBalance := make([]*big.Int, len(voters))
|
||||
txes = make([]*transaction.Transaction, 0, len(voters))
|
||||
gasBalance := make([]*big.Int, len(voters)-1)
|
||||
referenceGASBalance := make([]*big.Int, len(referenceAccounts)-1)
|
||||
neoBalance := make([]*big.Int, len(voters)-1)
|
||||
txes = make([]*transaction.Transaction, 0, len(voters)-1)
|
||||
var refTxFee int64
|
||||
for i := range voters {
|
||||
for i := range voters[:len(voters)-1] {
|
||||
h := voters[i].ScriptHash()
|
||||
refH := referenceAccounts[i].ScriptHash()
|
||||
gasBalance[i] = e.Chain.GetUtilityTokenBalance(h)
|
||||
|
@ -169,7 +171,7 @@ func TestNEO_Vote(t *testing.T) {
|
|||
|
||||
// GAS increase consists of 2 parts: NEO holding + voting for committee nodes.
|
||||
// Here we check that 2-nd part exists and is proportional to the amount of NEO given.
|
||||
for i := range voters {
|
||||
for i := range voters[:len(voters)-1] {
|
||||
newGAS := e.Chain.GetUtilityTokenBalance(voters[i].ScriptHash())
|
||||
newGAS.Sub(newGAS, gasBalance[i])
|
||||
gasForHold := referenceGASBalance[i]
|
||||
|
@ -197,6 +199,7 @@ func TestNEO_Vote(t *testing.T) {
|
|||
require.NoError(t, err)
|
||||
for i := range pubs {
|
||||
require.NotEqual(t, candidates[0], pubs[i])
|
||||
require.NotEqual(t, candidates[len(candidates)-1], pubs[i])
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -12,7 +12,6 @@ import (
|
|||
|
||||
"github.com/btcsuite/btcd/btcec"
|
||||
lru "github.com/hashicorp/golang-lru"
|
||||
"github.com/nspcc-dev/neo-go/pkg/core/interop/interopnames"
|
||||
"github.com/nspcc-dev/neo-go/pkg/crypto/hash"
|
||||
"github.com/nspcc-dev/neo-go/pkg/encoding/address"
|
||||
"github.com/nspcc-dev/neo-go/pkg/io"
|
||||
|
@ -319,8 +318,7 @@ func (p *PublicKey) GetVerificationScript() []byte {
|
|||
buf.WriteB(0xAC) // CHECKSIG
|
||||
return buf.Bytes()
|
||||
}
|
||||
emit.Bytes(buf.BinWriter, b)
|
||||
emit.Syscall(buf.BinWriter, interopnames.SystemCryptoCheckSig)
|
||||
emit.CheckSig(buf.BinWriter, b)
|
||||
|
||||
return buf.Bytes()
|
||||
}
|
||||
|
|
|
@ -219,6 +219,14 @@ func AppCall(w *io.BinWriter, scriptHash util.Uint160, operation string, f callf
|
|||
AppCallNoArgs(w, scriptHash, operation, f)
|
||||
}
|
||||
|
||||
// CheckSig emits a single-key verification script using given []bytes as a key.
|
||||
// It does not check for key correctness, so you can get an invalid script if the
|
||||
// data passed is not really a public key.
|
||||
func CheckSig(w *io.BinWriter, key []byte) {
|
||||
Bytes(w, key)
|
||||
Syscall(w, interopnames.SystemCryptoCheckSig)
|
||||
}
|
||||
|
||||
func isInstructionJmp(op opcode.Opcode) bool {
|
||||
return opcode.JMP <= op && op <= opcode.CALLL || op == opcode.ENDTRYL
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue