Merge pull request #1370 from nspcc-dev/fix/committee
Add committee to unit test chain, fix some bugs
This commit is contained in:
commit
7560aa345a
5 changed files with 71 additions and 10 deletions
|
@ -7,6 +7,8 @@ ProtocolConfiguration:
|
||||||
- 02103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e
|
- 02103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e
|
||||||
- 03d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee699
|
- 03d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee699
|
||||||
- 02a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd62
|
- 02a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd62
|
||||||
|
- 02c429b3ea1aa486cb2edfd6e99d8055c1f81f1a9206664e2c40a586d187257557
|
||||||
|
- 02c4de32252c50fa171dbe25379e4e2d55cdc12f69e382c39f59a44573ecff2f9d
|
||||||
ValidatorsCount: 4
|
ValidatorsCount: 4
|
||||||
SeedList:
|
SeedList:
|
||||||
- 127.0.0.1:20334
|
- 127.0.0.1:20334
|
||||||
|
|
|
@ -17,7 +17,6 @@ import (
|
||||||
"github.com/nspcc-dev/neo-go/pkg/crypto/hash"
|
"github.com/nspcc-dev/neo-go/pkg/crypto/hash"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/internal/testchain"
|
"github.com/nspcc-dev/neo-go/pkg/internal/testchain"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/io"
|
"github.com/nspcc-dev/neo-go/pkg/io"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/smartcontract"
|
|
||||||
"github.com/nspcc-dev/neo-go/pkg/smartcontract/trigger"
|
"github.com/nspcc-dev/neo-go/pkg/smartcontract/trigger"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/util"
|
"github.com/nspcc-dev/neo-go/pkg/util"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/vm"
|
"github.com/nspcc-dev/neo-go/pkg/vm"
|
||||||
|
@ -234,6 +233,9 @@ func TestVerifyTx(t *testing.T) {
|
||||||
emit.Opcode(w.BinWriter, opcode.ASSERT)
|
emit.Opcode(w.BinWriter, opcode.ASSERT)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
emit.AppCallWithOperationAndArgs(w.BinWriter, gasHash, "transfer",
|
||||||
|
neoOwner, testchain.CommitteeScriptHash(), int64(1_000_000_000))
|
||||||
|
emit.Opcode(w.BinWriter, opcode.ASSERT)
|
||||||
require.NoError(t, w.Err)
|
require.NoError(t, w.Err)
|
||||||
|
|
||||||
txMove := bc.newTestTx(neoOwner, w.Bytes())
|
txMove := bc.newTestTx(neoOwner, w.Bytes())
|
||||||
|
@ -355,13 +357,13 @@ func TestVerifyTx(t *testing.T) {
|
||||||
})
|
})
|
||||||
t.Run("ValidHighPriority", func(t *testing.T) {
|
t.Run("ValidHighPriority", func(t *testing.T) {
|
||||||
tx := bc.newTestTx(h, testScript)
|
tx := bc.newTestTx(h, testScript)
|
||||||
|
tx.Attributes = append(tx.Attributes, transaction.Attribute{Type: transaction.HighPriority})
|
||||||
tx.NetworkFee += 4_000_000 // multisig check
|
tx.NetworkFee += 4_000_000 // multisig check
|
||||||
tx.Signers = []transaction.Signer{{
|
tx.Signers = []transaction.Signer{{
|
||||||
Account: testchain.MultisigScriptHash(),
|
Account: testchain.CommitteeScriptHash(),
|
||||||
Scopes: transaction.FeeOnly,
|
Scopes: transaction.FeeOnly,
|
||||||
}}
|
}}
|
||||||
validators := bc.GetStandByValidators()
|
rawScript := testchain.CommitteeVerificationScript()
|
||||||
rawScript, err := smartcontract.CreateMajorityMultiSigRedeemScript(validators)
|
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
size := io.GetVarSize(tx)
|
size := io.GetVarSize(tx)
|
||||||
netFee, sizeDelta := CalculateNetworkFee(rawScript)
|
netFee, sizeDelta := CalculateNetworkFee(rawScript)
|
||||||
|
@ -369,7 +371,7 @@ func TestVerifyTx(t *testing.T) {
|
||||||
tx.NetworkFee += int64(size+sizeDelta) * bc.FeePerByte()
|
tx.NetworkFee += int64(size+sizeDelta) * bc.FeePerByte()
|
||||||
data := tx.GetSignedPart()
|
data := tx.GetSignedPart()
|
||||||
tx.Scripts = []transaction.Witness{{
|
tx.Scripts = []transaction.Witness{{
|
||||||
InvocationScript: testchain.Sign(data),
|
InvocationScript: testchain.SignCommittee(data),
|
||||||
VerificationScript: rawScript,
|
VerificationScript: rawScript,
|
||||||
}}
|
}}
|
||||||
require.NoError(t, bc.VerifyTx(tx))
|
require.NoError(t, bc.VerifyTx(tx))
|
||||||
|
|
|
@ -485,13 +485,13 @@ func (n *NEO) GetCommitteeMembers(bc blockchainer.Blockchainer, d dao.DAO) (keys
|
||||||
votersCount.Mul(votersCount, big.NewInt(effectiveVoterTurnout))
|
votersCount.Mul(votersCount, big.NewInt(effectiveVoterTurnout))
|
||||||
voterTurnout := votersCount.Div(votersCount, n.getTotalSupply(d))
|
voterTurnout := votersCount.Div(votersCount, n.getTotalSupply(d))
|
||||||
if voterTurnout.Sign() != 1 {
|
if voterTurnout.Sign() != 1 {
|
||||||
return bc.GetStandByValidators(), nil
|
return bc.GetStandByCommittee(), nil
|
||||||
}
|
}
|
||||||
cs, err := n.getCandidates(d)
|
cs, err := n.getCandidates(d)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
sbVals := bc.GetStandByValidators()
|
sbVals := bc.GetStandByCommittee()
|
||||||
count := len(sbVals)
|
count := len(sbVals)
|
||||||
if len(cs) < count {
|
if len(cs) < count {
|
||||||
return sbVals, nil
|
return sbVals, nil
|
||||||
|
|
|
@ -83,6 +83,11 @@ func TestNEO_Vote(t *testing.T) {
|
||||||
ic.VM.Load(priv.PublicKey().GetVerificationScript())
|
ic.VM.Load(priv.PublicKey().GetVerificationScript())
|
||||||
require.NoError(t, neo.VoteInternal(ic, h, candidates[0]))
|
require.NoError(t, neo.VoteInternal(ic, h, candidates[0]))
|
||||||
|
|
||||||
|
for i := testchain.ValidatorsCount; i < testchain.CommitteeSize(); i++ {
|
||||||
|
priv := testchain.PrivateKey(i)
|
||||||
|
require.NoError(t, neo.RegisterCandidateInternal(ic, priv.PublicKey()))
|
||||||
|
}
|
||||||
|
|
||||||
pubs, err = neo.GetValidatorsInternal(bc, ic.DAO)
|
pubs, err = neo.GetValidatorsInternal(bc, ic.DAO)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
sortedCandidates := candidates.Copy()
|
sortedCandidates := candidates.Copy()
|
||||||
|
|
|
@ -23,18 +23,31 @@ var privNetKeys = []string{
|
||||||
"KzgWE3u3EDp13XPXXuTKZxeJ3Gi8Bsm8f9ijY3ZsCKKRvZUo1Cdn",
|
"KzgWE3u3EDp13XPXXuTKZxeJ3Gi8Bsm8f9ijY3ZsCKKRvZUo1Cdn",
|
||||||
"KxyjQ8eUa4FHt3Gvioyt1Wz29cTUrE4eTqX3yFSk1YFCsPL8uNsY",
|
"KxyjQ8eUa4FHt3Gvioyt1Wz29cTUrE4eTqX3yFSk1YFCsPL8uNsY",
|
||||||
"L2oEXKRAAMiPEZukwR5ho2S6SMeQLhcK9mF71ZnF7GvT8dU4Kkgz",
|
"L2oEXKRAAMiPEZukwR5ho2S6SMeQLhcK9mF71ZnF7GvT8dU4Kkgz",
|
||||||
|
|
||||||
|
// Provide 2 committee extra members so that committee address differs from
|
||||||
|
// the validators one.
|
||||||
|
"L1Tr1iq5oz1jaFaMXP21sHDkJYDDkuLtpvQ4wRf1cjKvJYvnvpAb",
|
||||||
|
"Kz6XTUrExy78q8f4MjDHnwz8fYYyUE8iPXwPRAkHa3qN2JcHYm7e",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ValidatorsCount returns number of validators in the testchain.
|
||||||
|
const ValidatorsCount = 4
|
||||||
|
|
||||||
var (
|
var (
|
||||||
// ids maps validators order by public key sorting to validators ID.
|
// ids maps validators order by public key sorting to validators ID.
|
||||||
// which is an order of the validator in the StandByValidators list.
|
// which is an order of the validator in the StandByValidators list.
|
||||||
ids = []int{1, 3, 0, 2}
|
ids = []int{1, 3, 0, 2, 4, 5}
|
||||||
// orders maps to validators id to it's order by public key sorting.
|
// orders maps to validators id to it's order by public key sorting.
|
||||||
orders = []int{2, 0, 3, 1}
|
orders = []int{2, 0, 3, 1, 4, 5}
|
||||||
)
|
)
|
||||||
|
|
||||||
// Size returns testchain initial validators amount.
|
// Size returns testchain initial validators amount.
|
||||||
func Size() int {
|
func Size() int {
|
||||||
|
return ValidatorsCount
|
||||||
|
}
|
||||||
|
|
||||||
|
// CommitteeSize returns testchain committee size.
|
||||||
|
func CommitteeSize() int {
|
||||||
return len(privNetKeys)
|
return len(privNetKeys)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -66,7 +79,7 @@ func PrivateKeyByID(id int) *keys.PrivateKey {
|
||||||
// MultisigVerificationScript returns script hash of the consensus multisig address.
|
// MultisigVerificationScript returns script hash of the consensus multisig address.
|
||||||
func MultisigVerificationScript() []byte {
|
func MultisigVerificationScript() []byte {
|
||||||
var pubs keys.PublicKeys
|
var pubs keys.PublicKeys
|
||||||
for i := range privNetKeys {
|
for i := range privNetKeys[:ValidatorsCount] {
|
||||||
priv := PrivateKey(ids[i])
|
priv := PrivateKey(ids[i])
|
||||||
pubs = append(pubs, priv.PublicKey())
|
pubs = append(pubs, priv.PublicKey())
|
||||||
}
|
}
|
||||||
|
@ -88,6 +101,31 @@ func MultisigAddress() string {
|
||||||
return address.Uint160ToString(MultisigScriptHash())
|
return address.Uint160ToString(MultisigScriptHash())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CommitteeVerificationScript returns script hash of the committee multisig address.
|
||||||
|
func CommitteeVerificationScript() []byte {
|
||||||
|
var pubs keys.PublicKeys
|
||||||
|
for i := range privNetKeys {
|
||||||
|
priv := PrivateKey(ids[i])
|
||||||
|
pubs = append(pubs, priv.PublicKey())
|
||||||
|
}
|
||||||
|
|
||||||
|
script, err := smartcontract.CreateMajorityMultiSigRedeemScript(pubs)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return script
|
||||||
|
}
|
||||||
|
|
||||||
|
// CommitteeScriptHash returns committee address as Uint160.
|
||||||
|
func CommitteeScriptHash() util.Uint160 {
|
||||||
|
return hash.Hash160(CommitteeVerificationScript())
|
||||||
|
}
|
||||||
|
|
||||||
|
// CommitteeAddress return committee address as string.
|
||||||
|
func CommitteeAddress() string {
|
||||||
|
return address.Uint160ToString(CommitteeScriptHash())
|
||||||
|
}
|
||||||
|
|
||||||
// Sign signs data by all consensus nodes and returns invocation script.
|
// Sign signs data by all consensus nodes and returns invocation script.
|
||||||
func Sign(data []byte) []byte {
|
func Sign(data []byte) []byte {
|
||||||
buf := io.NewBufBinWriter()
|
buf := io.NewBufBinWriter()
|
||||||
|
@ -102,6 +140,20 @@ func Sign(data []byte) []byte {
|
||||||
return buf.Bytes()
|
return buf.Bytes()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SignCommittee signs data by a majority of committee members.
|
||||||
|
func SignCommittee(data []byte) []byte {
|
||||||
|
buf := io.NewBufBinWriter()
|
||||||
|
for i := 0; i < CommitteeSize()/2+1; i++ {
|
||||||
|
pKey := PrivateKey(i)
|
||||||
|
sig := pKey.Sign(data)
|
||||||
|
if len(sig) != 64 {
|
||||||
|
panic("wrong signature length")
|
||||||
|
}
|
||||||
|
emit.Bytes(buf.BinWriter, sig)
|
||||||
|
}
|
||||||
|
return buf.Bytes()
|
||||||
|
}
|
||||||
|
|
||||||
// NewBlock creates new block for the given blockchain with the given offset
|
// NewBlock creates new block for the given blockchain with the given offset
|
||||||
// (usually, 1), primary node index and transactions.
|
// (usually, 1), primary node index and transactions.
|
||||||
func NewBlock(t *testing.T, bc blockchainer.Blockchainer, offset uint32, primary uint32, txs ...*transaction.Transaction) *block.Block {
|
func NewBlock(t *testing.T, bc blockchainer.Blockchainer, offset uint32, primary uint32, txs ...*transaction.Transaction) *block.Block {
|
||||||
|
|
Loading…
Reference in a new issue