mirror of
https://github.com/nspcc-dev/neo-go.git
synced 2024-11-26 19:42:23 +00:00
state: drop Network from MPTRoot structure
It's only needed to verify/sign.
This commit is contained in:
parent
f91ff78918
commit
8c110a6147
10 changed files with 20 additions and 42 deletions
|
@ -1,9 +1,6 @@
|
||||||
package state
|
package state
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/binary"
|
|
||||||
|
|
||||||
"github.com/nspcc-dev/neo-go/pkg/config/netmode"
|
|
||||||
"github.com/nspcc-dev/neo-go/pkg/core/transaction"
|
"github.com/nspcc-dev/neo-go/pkg/core/transaction"
|
||||||
"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/io"
|
"github.com/nspcc-dev/neo-go/pkg/io"
|
||||||
|
@ -12,27 +9,12 @@ import (
|
||||||
|
|
||||||
// MPTRoot represents storage state root together with sign info.
|
// MPTRoot represents storage state root together with sign info.
|
||||||
type MPTRoot struct {
|
type MPTRoot struct {
|
||||||
Network netmode.Magic `json:"-"`
|
|
||||||
Version byte `json:"version"`
|
Version byte `json:"version"`
|
||||||
Index uint32 `json:"index"`
|
Index uint32 `json:"index"`
|
||||||
Root util.Uint256 `json:"stateroot"`
|
Root util.Uint256 `json:"stateroot"`
|
||||||
Witness *transaction.Witness `json:"witness,omitempty"`
|
Witness *transaction.Witness `json:"witness,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetSignedPart returns part of MPTRootBase which needs to be signed.
|
|
||||||
func (s *MPTRoot) GetSignedPart() []byte {
|
|
||||||
b := make([]byte, 4+32)
|
|
||||||
binary.LittleEndian.PutUint32(b, uint32(s.Network))
|
|
||||||
h := s.Hash()
|
|
||||||
copy(b[4:], h[:])
|
|
||||||
return b
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetSignedHash returns hash of MPTRootBase which needs to be signed.
|
|
||||||
func (s *MPTRoot) GetSignedHash() util.Uint256 {
|
|
||||||
return hash.Sha256(s.GetSignedPart())
|
|
||||||
}
|
|
||||||
|
|
||||||
// Hash returns hash of s.
|
// Hash returns hash of s.
|
||||||
func (s *MPTRoot) Hash() util.Uint256 {
|
func (s *MPTRoot) Hash() util.Uint256 {
|
||||||
buf := io.NewBufBinWriter()
|
buf := io.NewBufBinWriter()
|
||||||
|
|
|
@ -116,9 +116,8 @@ func (s *Module) AddMPTBatch(index uint32, b mpt.Batch) error {
|
||||||
}
|
}
|
||||||
s.mpt.Flush()
|
s.mpt.Flush()
|
||||||
err := s.addLocalStateRoot(&state.MPTRoot{
|
err := s.addLocalStateRoot(&state.MPTRoot{
|
||||||
Network: s.network,
|
Index: index,
|
||||||
Index: index,
|
Root: s.mpt.StateRoot(),
|
||||||
Root: s.mpt.StateRoot(),
|
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
|
|
@ -46,7 +46,7 @@ func (s *Module) getStateRoot(key []byte) (*state.MPTRoot, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
sr := &state.MPTRoot{Network: s.network}
|
sr := &state.MPTRoot{}
|
||||||
r := io.NewBinReaderFromBuf(data)
|
r := io.NewBinReaderFromBuf(data)
|
||||||
sr.DecodeBinary(r)
|
sr.DecodeBinary(r)
|
||||||
return sr, r.Err
|
return sr, r.Err
|
||||||
|
|
|
@ -33,7 +33,7 @@ func testSignStateRoot(t *testing.T, r *state.MPTRoot, pubs keys.PublicKeys, acc
|
||||||
n := smartcontract.GetMajorityHonestNodeCount(len(accs))
|
n := smartcontract.GetMajorityHonestNodeCount(len(accs))
|
||||||
w := io.NewBufBinWriter()
|
w := io.NewBufBinWriter()
|
||||||
for i := 0; i < n; i++ {
|
for i := 0; i < n; i++ {
|
||||||
sig := accs[i].PrivateKey().SignHash(r.GetSignedHash())
|
sig := accs[i].PrivateKey().SignHashable(uint32(netmode.UnitTestNet), r)
|
||||||
emit.Bytes(w.BinWriter, sig)
|
emit.Bytes(w.BinWriter, sig)
|
||||||
}
|
}
|
||||||
require.NoError(t, w.Err)
|
require.NoError(t, w.Err)
|
||||||
|
@ -44,7 +44,7 @@ func testSignStateRoot(t *testing.T, r *state.MPTRoot, pubs keys.PublicKeys, acc
|
||||||
VerificationScript: script,
|
VerificationScript: script,
|
||||||
InvocationScript: w.Bytes(),
|
InvocationScript: w.Bytes(),
|
||||||
}
|
}
|
||||||
data, err := testserdes.EncodeBinary(stateroot.NewMessage(netmode.UnitTestNet, stateroot.RootT, r))
|
data, err := testserdes.EncodeBinary(stateroot.NewMessage(stateroot.RootT, r))
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
return data
|
return data
|
||||||
}
|
}
|
||||||
|
@ -97,7 +97,7 @@ func TestStateRoot(t *testing.T) {
|
||||||
t.Run("drop zero index", func(t *testing.T) {
|
t.Run("drop zero index", func(t *testing.T) {
|
||||||
r, err := srv.GetStateRoot(0)
|
r, err := srv.GetStateRoot(0)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
data, err := testserdes.EncodeBinary(stateroot.NewMessage(netmode.UnitTestNet, stateroot.RootT, r))
|
data, err := testserdes.EncodeBinary(stateroot.NewMessage(stateroot.RootT, r))
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.NoError(t, srv.OnPayload(&payload.Extensible{Data: data}))
|
require.NoError(t, srv.OnPayload(&payload.Extensible{Data: data}))
|
||||||
require.EqualValues(t, 0, srv.CurrentValidatedHeight())
|
require.EqualValues(t, 0, srv.CurrentValidatedHeight())
|
||||||
|
@ -221,7 +221,7 @@ func TestStateRootFull(t *testing.T) {
|
||||||
|
|
||||||
r, err := srv.GetStateRoot(2)
|
r, err := srv.GetStateRoot(2)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.NoError(t, srv.AddSignature(2, 0, accs[0].PrivateKey().SignHash(r.GetSignedHash())))
|
require.NoError(t, srv.AddSignature(2, 0, accs[0].PrivateKey().SignHashable(uint32(netmode.UnitTestNet), r)))
|
||||||
require.NotNil(t, lastValidated.Load().(*payload.Extensible))
|
require.NotNil(t, lastValidated.Load().(*payload.Extensible))
|
||||||
|
|
||||||
msg := new(stateroot.Message)
|
msg := new(stateroot.Message)
|
||||||
|
@ -250,5 +250,5 @@ func checkVoteBroadcasted(t *testing.T, bc *Blockchain, p *payload.Extensible,
|
||||||
|
|
||||||
pubs, _, err := bc.contracts.Designate.GetDesignatedByRole(bc.dao, noderoles.StateValidator, bc.BlockHeight())
|
pubs, _, err := bc.contracts.Designate.GetDesignatedByRole(bc.dao, noderoles.StateValidator, bc.BlockHeight())
|
||||||
require.True(t, len(pubs) > int(valIndex))
|
require.True(t, len(pubs) > int(valIndex))
|
||||||
require.True(t, pubs[valIndex].Verify(vote.Signature, r.GetSignedHash().BytesBE()))
|
require.True(t, pubs[valIndex].VerifyHashable(vote.Signature, uint32(netmode.UnitTestNet), r))
|
||||||
}
|
}
|
||||||
|
|
|
@ -1364,7 +1364,7 @@ func testRPCProtocol(t *testing.T, doRPCCall func(string, string, *testing.T) []
|
||||||
body := doRPCCall(rpc, httpSrv.URL, t)
|
body := doRPCCall(rpc, httpSrv.URL, t)
|
||||||
rawRes := checkErrGetResult(t, body, false)
|
rawRes := checkErrGetResult(t, body, false)
|
||||||
|
|
||||||
res := &state.MPTRoot{Network: netmode.UnitTestNet}
|
res := &state.MPTRoot{}
|
||||||
require.NoError(t, json.Unmarshal(rawRes, res))
|
require.NoError(t, json.Unmarshal(rawRes, res))
|
||||||
require.NotEqual(t, util.Uint256{}, res.Root) // be sure this test uses valid height
|
require.NotEqual(t, util.Uint256{}, res.Root) // be sure this test uses valid height
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,6 @@ package stateroot
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/nspcc-dev/neo-go/pkg/config/netmode"
|
|
||||||
"github.com/nspcc-dev/neo-go/pkg/core/state"
|
"github.com/nspcc-dev/neo-go/pkg/core/state"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/io"
|
"github.com/nspcc-dev/neo-go/pkg/io"
|
||||||
)
|
)
|
||||||
|
@ -14,7 +13,6 @@ type (
|
||||||
|
|
||||||
// Message represents state-root related message.
|
// Message represents state-root related message.
|
||||||
Message struct {
|
Message struct {
|
||||||
Network netmode.Magic
|
|
||||||
Type MessageType
|
Type MessageType
|
||||||
Payload io.Serializable
|
Payload io.Serializable
|
||||||
}
|
}
|
||||||
|
@ -27,9 +25,8 @@ const (
|
||||||
)
|
)
|
||||||
|
|
||||||
// NewMessage creates new message of specified type.
|
// NewMessage creates new message of specified type.
|
||||||
func NewMessage(net netmode.Magic, typ MessageType, p io.Serializable) *Message {
|
func NewMessage(typ MessageType, p io.Serializable) *Message {
|
||||||
return &Message{
|
return &Message{
|
||||||
Network: net,
|
|
||||||
Type: typ,
|
Type: typ,
|
||||||
Payload: p,
|
Payload: p,
|
||||||
}
|
}
|
||||||
|
@ -47,7 +44,7 @@ func (m *Message) DecodeBinary(r *io.BinReader) {
|
||||||
case VoteT:
|
case VoteT:
|
||||||
m.Payload = new(Vote)
|
m.Payload = new(Vote)
|
||||||
case RootT:
|
case RootT:
|
||||||
m.Payload = &state.MPTRoot{Network: m.Network}
|
m.Payload = new(state.MPTRoot)
|
||||||
default:
|
default:
|
||||||
r.Err = fmt.Errorf("invalid type: %x", m.Type)
|
r.Err = fmt.Errorf("invalid type: %x", m.Type)
|
||||||
return
|
return
|
||||||
|
|
|
@ -40,7 +40,7 @@ func (s *service) AddSignature(height uint32, validatorIndex int32, sig []byte)
|
||||||
|
|
||||||
incRoot.Lock()
|
incRoot.Lock()
|
||||||
if incRoot.root != nil {
|
if incRoot.root != nil {
|
||||||
ok := pub.Verify(sig, incRoot.root.GetSignedHash().BytesBE())
|
ok := pub.VerifyHashable(sig, uint32(s.Network), incRoot.root)
|
||||||
if !ok {
|
if !ok {
|
||||||
incRoot.Unlock()
|
incRoot.Unlock()
|
||||||
return fmt.Errorf("invalid state root signature for %d", validatorIndex)
|
return fmt.Errorf("invalid state root signature for %d", validatorIndex)
|
||||||
|
@ -78,7 +78,7 @@ func (s *service) getIncompleteRoot(height uint32) *incompleteRoot {
|
||||||
|
|
||||||
func (s *service) sendValidatedRoot(r *state.MPTRoot, priv *keys.PrivateKey) {
|
func (s *service) sendValidatedRoot(r *state.MPTRoot, priv *keys.PrivateKey) {
|
||||||
w := io.NewBufBinWriter()
|
w := io.NewBufBinWriter()
|
||||||
m := NewMessage(s.Network, RootT, r)
|
m := NewMessage(RootT, r)
|
||||||
m.EncodeBinary(w.BinWriter)
|
m.EncodeBinary(w.BinWriter)
|
||||||
ep := &payload.Extensible{
|
ep := &payload.Extensible{
|
||||||
ValidBlockStart: r.Index,
|
ValidBlockStart: r.Index,
|
||||||
|
|
|
@ -95,7 +95,7 @@ func New(cfg config.StateRoot, log *zap.Logger, bc blockchainer.Blockchainer) (S
|
||||||
|
|
||||||
// OnPayload implements Service interface.
|
// OnPayload implements Service interface.
|
||||||
func (s *service) OnPayload(ep *payload.Extensible) error {
|
func (s *service) OnPayload(ep *payload.Extensible) error {
|
||||||
m := &Message{Network: s.Network}
|
m := &Message{}
|
||||||
r := io.NewBinReaderFromBuf(ep.Data)
|
r := io.NewBinReaderFromBuf(ep.Data)
|
||||||
m.DecodeBinary(r)
|
m.DecodeBinary(r)
|
||||||
if r.Err != nil {
|
if r.Err != nil {
|
||||||
|
|
|
@ -3,6 +3,7 @@ package stateroot
|
||||||
import (
|
import (
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
|
"github.com/nspcc-dev/neo-go/pkg/config/netmode"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/core/state"
|
"github.com/nspcc-dev/neo-go/pkg/core/state"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/core/transaction"
|
"github.com/nspcc-dev/neo-go/pkg/core/transaction"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
||||||
|
@ -38,11 +39,10 @@ func newIncompleteRoot() *incompleteRoot {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *incompleteRoot) reverify() {
|
func (r *incompleteRoot) reverify(net netmode.Magic) {
|
||||||
txHash := r.root.GetSignedHash()
|
|
||||||
for _, sig := range r.sigs {
|
for _, sig := range r.sigs {
|
||||||
if !sig.ok {
|
if !sig.ok {
|
||||||
sig.ok = sig.pub.Verify(sig.sig, txHash.BytesBE())
|
sig.ok = sig.pub.VerifyHashable(sig.sig, uint32(net), r.root)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,16 +47,16 @@ func (s *service) signAndSend(r *state.MPTRoot) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
sig := acc.PrivateKey().SignHash(r.GetSignedHash())
|
sig := acc.PrivateKey().SignHashable(uint32(s.Network), r)
|
||||||
incRoot := s.getIncompleteRoot(r.Index)
|
incRoot := s.getIncompleteRoot(r.Index)
|
||||||
incRoot.root = r
|
incRoot.root = r
|
||||||
incRoot.addSignature(acc.PrivateKey().PublicKey(), sig)
|
incRoot.addSignature(acc.PrivateKey().PublicKey(), sig)
|
||||||
incRoot.reverify()
|
incRoot.reverify(s.Network)
|
||||||
|
|
||||||
s.accMtx.RLock()
|
s.accMtx.RLock()
|
||||||
myIndex := s.myIndex
|
myIndex := s.myIndex
|
||||||
s.accMtx.RUnlock()
|
s.accMtx.RUnlock()
|
||||||
msg := NewMessage(s.Network, VoteT, &Vote{
|
msg := NewMessage(VoteT, &Vote{
|
||||||
ValidatorIndex: int32(myIndex),
|
ValidatorIndex: int32(myIndex),
|
||||||
Height: r.Index,
|
Height: r.Index,
|
||||||
Signature: sig,
|
Signature: sig,
|
||||||
|
|
Loading…
Reference in a new issue