Merge pull request #767 from nspcc-dev/state-tx-verifications

State tx verifications
This commit is contained in:
Roman Khimov 2020-03-17 11:35:08 +03:00 committed by GitHub
commit fea86a8053
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -1387,6 +1387,63 @@ func (bc *Blockchain) verifyTx(t *transaction.Transaction, block *block.Block) e
if inv.Gas.FractionalValue() != 0 { if inv.Gas.FractionalValue() != 0 {
return errors.New("invocation gas can only be integer") return errors.New("invocation gas can only be integer")
} }
case transaction.StateType:
stx := t.Data.(*transaction.StateTX)
for _, desc := range stx.Descriptors {
switch desc.Type {
case transaction.Account:
if desc.Field != "Votes" {
return errors.New("bad field in account descriptor")
}
votes := keys.PublicKeys{}
err := votes.DecodeBytes(desc.Value)
if err != nil {
return err
}
if len(votes) > state.MaxValidatorsVoted {
return errors.New("voting candidate limit exceeded")
}
hash, err := util.Uint160DecodeBytesBE(desc.Key)
if err != nil {
return err
}
account, err := bc.dao.GetAccountStateOrNew(hash)
if err != nil {
return err
}
if account.IsFrozen {
return errors.New("account is frozen")
}
if votes.Len() > 0 {
balance := account.GetBalanceValues()[GoverningTokenID()]
if balance == 0 {
return errors.New("no governing tokens available to vote")
}
validators, err := bc.GetEnrollments()
if err != nil {
return err
}
for _, k := range votes {
var isRegistered bool
for i := range validators {
if k.Equal(validators[i].PublicKey) {
isRegistered = true
break
}
}
if !isRegistered {
return errors.New("vote for unregistered validator")
}
}
}
case transaction.Validator:
if desc.Field != "Registered" {
return errors.New("bad field in validator descriptor")
}
default:
return errors.New("bad descriptor type")
}
}
} }
return bc.verifyTxWitnesses(t, block) return bc.verifyTxWitnesses(t, block)
@ -1885,6 +1942,31 @@ func (bc *Blockchain) GetScriptHashesForVerifying(t *transaction.Transaction) ([
case transaction.EnrollmentType: case transaction.EnrollmentType:
etx := t.Data.(*transaction.EnrollmentTX) etx := t.Data.(*transaction.EnrollmentTX)
hashes[etx.PublicKey.GetScriptHash()] = true hashes[etx.PublicKey.GetScriptHash()] = true
case transaction.StateType:
stx := t.Data.(*transaction.StateTX)
for _, desc := range stx.Descriptors {
switch desc.Type {
case transaction.Account:
if desc.Field != "Votes" {
return nil, errors.New("bad account state descriptor")
}
hash, err := util.Uint160DecodeBytesBE(desc.Key)
if err != nil {
return nil, err
}
hashes[hash] = true
case transaction.Validator:
if desc.Field != "Registered" {
return nil, errors.New("bad validator state descriptor")
}
key := &keys.PublicKey{}
err := key.DecodeBytes(desc.Key)
if err != nil {
return nil, err
}
hashes[key.GetScriptHash()] = true
}
}
} }
// convert hashes to []util.Uint160 // convert hashes to []util.Uint160
hashesResult := make([]util.Uint160, 0, len(hashes)) hashesResult := make([]util.Uint160, 0, len(hashes))