Signed-off-by: Pavel Karpy <p.karpy@yadro.com>
This commit is contained in:
Pavel Karpy 2023-03-24 06:30:02 +03:00
parent 34329d67ff
commit 44e0124a54
2 changed files with 122 additions and 100 deletions

View file

@ -24,8 +24,6 @@ linters-settings:
govet: govet:
# report about shadowed variables # report about shadowed variables
check-shadowing: false check-shadowing: false
staticcheck:
checks: ["all", "-SA1019"] # TODO Enable SA1019 after deprecated warning are fixed.
funlen: funlen:
lines: 80 # default 60 lines: 80 # default 60
statements: 60 # default 40 statements: 60 # default 40

View file

@ -16,10 +16,13 @@ import (
"github.com/nspcc-dev/neo-go/pkg/crypto/keys" "github.com/nspcc-dev/neo-go/pkg/crypto/keys"
"github.com/nspcc-dev/neo-go/pkg/encoding/fixedn" "github.com/nspcc-dev/neo-go/pkg/encoding/fixedn"
"github.com/nspcc-dev/neo-go/pkg/neorpc" "github.com/nspcc-dev/neo-go/pkg/neorpc"
"github.com/nspcc-dev/neo-go/pkg/neorpc/result"
"github.com/nspcc-dev/neo-go/pkg/rpcclient/actor"
"github.com/nspcc-dev/neo-go/pkg/rpcclient/notary" "github.com/nspcc-dev/neo-go/pkg/rpcclient/notary"
sc "github.com/nspcc-dev/neo-go/pkg/smartcontract" sc "github.com/nspcc-dev/neo-go/pkg/smartcontract"
"github.com/nspcc-dev/neo-go/pkg/util" "github.com/nspcc-dev/neo-go/pkg/util"
"github.com/nspcc-dev/neo-go/pkg/vm/opcode" "github.com/nspcc-dev/neo-go/pkg/vm/opcode"
"github.com/nspcc-dev/neo-go/pkg/vm/vmstate"
"github.com/nspcc-dev/neo-go/pkg/wallet" "github.com/nspcc-dev/neo-go/pkg/wallet"
"go.uber.org/zap" "go.uber.org/zap"
) )
@ -34,6 +37,8 @@ type (
notary util.Uint160 notary util.Uint160
proxy util.Uint160 proxy util.Uint160
act notary.Actor
} }
notaryCfg struct { notaryCfg struct {
@ -462,34 +467,34 @@ func (c *Client) notaryInvoke(committee, invokedByAlpha bool, contract util.Uint
if err != nil { if err != nil {
return err return err
} }
//
params, err := invocationParams(args...) //params, err := invocationParams(args...)
if err != nil { //if err != nil {
return err // return err
} //}
//
// make test invocation of the method //// make test invocation of the method
test, err := c.client.InvokeFunction(contract, method, params, cosigners) //test, err := c.client.InvokeFunction(contract, method, params, cosigners)
if err != nil { //if err != nil {
return err // return err
} //}
//
// check invocation state //// check invocation state
if test.State != HaltState { //if test.State != HaltState {
return wrapFrostFSError(&notHaltStateError{state: test.State, exception: test.FaultException}) // return wrapFrostFSError(&notHaltStateError{state: test.State, exception: test.FaultException})
} //}
//
// if test invocation failed, then return error //// if test invocation failed, then return error
if len(test.Script) == 0 { //if len(test.Script) == 0 {
return wrapFrostFSError(errEmptyInvocationScript) // return wrapFrostFSError(errEmptyInvocationScript)
} //}
//
// after test invocation we build main multisig transaction //// after test invocation we build main multisig transaction
//
multiaddrAccount, err := c.notaryMultisigAccount(alphabetList, committee, invokedByAlpha) //multiaddrAccount, err := c.notaryMultisigAccount(alphabetList, committee, invokedByAlpha)
if err != nil { //if err != nil {
return err // return err
} //}
var until uint32 var until uint32
@ -502,47 +507,21 @@ func (c *Client) notaryInvoke(committee, invokedByAlpha bool, contract util.Uint
} }
} }
// prepare main tx nAct, err := notary.NewActor(c.client, cosigners, c.acc)
mainTx := &transaction.Transaction{
Nonce: nonce,
SystemFee: test.GasConsumed,
ValidUntilBlock: until,
Script: test.Script,
Attributes: []transaction.Attribute{
{
Type: transaction.NotaryAssistedT,
Value: &transaction.NotaryAssisted{NKeys: u8n},
},
},
Signers: cosigners,
}
// calculate notary fee
notaryFee, err := c.client.CalculateNotaryFee(u8n)
if err != nil { if err != nil {
return err return err
} }
// add network fee for cosigners h, _, _, err := nAct.Notarize(nAct.MakeTunedCall(contract, method, nil, func(r *result.Invoke, t *transaction.Transaction) error {
//nolint:staticcheck // waits for neo-go v0.99.3 with notary actors if r.State != vmstate.Halt.String() {
err = c.client.AddNetworkFee( return wrapFrostFSError(&notHaltStateError{state: r.State, exception: r.FaultException})
mainTx, }
notaryFee,
c.notaryAccounts(invokedByAlpha, multiaddrAccount)...,
)
if err != nil {
return err
}
// define witnesses t.ValidUntilBlock = until
mainTx.Scripts = c.notaryWitnesses(invokedByAlpha, multiaddrAccount, mainTx) t.Nonce = nonce
resp, err := c.client.SignAndPushP2PNotaryRequest(mainTx, return nil
[]byte{byte(opcode.RET)}, }, args...))
-1,
0,
c.notary.fallbackTime,
c.acc)
if err != nil && !alreadyOnChainError(err) { if err != nil && !alreadyOnChainError(err) {
return err return err
} }
@ -551,53 +530,98 @@ func (c *Client) notaryInvoke(committee, invokedByAlpha bool, contract util.Uint
zap.String("method", method), zap.String("method", method),
zap.Uint32("valid_until_block", until), zap.Uint32("valid_until_block", until),
zap.Uint32("fallback_valid_for", c.notary.fallbackTime), zap.Uint32("fallback_valid_for", c.notary.fallbackTime),
zap.Stringer("tx_hash", resp.Hash().Reverse())) zap.Stringer("tx_hash", h.Reverse()))
//// prepare main tx
//mainTx := &transaction.Transaction{
// Nonce: nonce,
// SystemFee: test.GasConsumed,
// ValidUntilBlock: until,
// Script: test.Script,
// Attributes: []transaction.Attribute{
// {
// Type: transaction.NotaryAssistedT,
// Value: &transaction.NotaryAssisted{NKeys: u8n},
// },
// },
// Signers: cosigners,
//}
//
//// calculate notary fee
//notaryFee, err := c.client.CalculateNotaryFee(u8n)
//if err != nil {
// return err
//}
//
//// add network fee for cosigners
////nolint:staticcheck // waits for neo-go v0.99.3 with notary actors
//err = c.client.AddNetworkFee(
// mainTx,
// notaryFee,
// c.notaryAccounts(invokedByAlpha, multiaddrAccount)...,
//)
//if err != nil {
// return err
//}
//
//// define witnesses
//mainTx.Scripts = c.notaryWitnesses(invokedByAlpha, multiaddrAccount, mainTx)
//
//resp, err := c.client.SignAndPushP2PNotaryRequest(mainTx,
// []byte{byte(opcode.RET)},
// -1,
// 0,
// c.notary.fallbackTime,
// c.acc)
//if err != nil && !alreadyOnChainError(err) {
// return err
//}
return nil return nil
} }
func (c *Client) notaryCosigners(invokedByAlpha bool, ir []*keys.PublicKey, committee bool) ([]transaction.Signer, error) { func (c *Client) notaryCosigners(invokedByAlpha bool, ir []*keys.PublicKey, committee bool) ([]actor.SignerAccount, error) {
s := make([]transaction.Signer, 0, 4) multiaddrAccount, err := c.notaryMultisigAccount(ir, committee, invokedByAlpha)
// first we have proxy contract signature, as it will pay for the execution
s = append(s, transaction.Signer{
Account: c.notary.proxy,
Scopes: transaction.None,
})
// then we have inner ring multiaddress signature
m := sigCount(ir, committee)
multisigScript, err := sc.CreateMultiSigRedeemScript(m, ir)
if err != nil { if err != nil {
// wrap error as FrostFS-specific since the call is not related to any client return nil, err
return nil, wrapFrostFSError(fmt.Errorf("can't create ir multisig redeem script: %w", err))
} }
s = append(s, transaction.Signer{ ss := make([]actor.SignerAccount, 0, 3)
Account: hash.Hash160(multisigScript), ss = append(ss, []actor.SignerAccount{
Scopes: c.signer.Scopes, {
AllowedContracts: c.signer.AllowedContracts, // proxy contract
AllowedGroups: c.signer.AllowedGroups, Signer: transaction.Signer{
}) Account: c.notary.proxy,
Scopes: transaction.None,
},
Account: notary.FakeContractAccount(c.notary.proxy),
},
{
// multi signature
Signer: transaction.Signer{
Account: multiaddrAccount.ScriptHash(),
Scopes: c.signer.Scopes,
AllowedContracts: c.signer.AllowedContracts,
AllowedGroups: c.signer.AllowedGroups,
},
Account: multiaddrAccount,
},
}...)
if !invokedByAlpha { if !invokedByAlpha {
// then we have invoker signature // invoker signature
s = append(s, transaction.Signer{ ss = append(ss, actor.SignerAccount{
Account: hash.Hash160(c.acc.GetVerificationScript()), Signer: transaction.Signer{
Scopes: c.signer.Scopes, Account: hash.Hash160(c.acc.GetVerificationScript()),
AllowedContracts: c.signer.AllowedContracts, Scopes: c.signer.Scopes,
AllowedGroups: c.signer.AllowedGroups, AllowedContracts: c.signer.AllowedContracts,
AllowedGroups: c.signer.AllowedGroups,
},
Account: c.acc,
}) })
} }
// last one is a placeholder for notary contract signature return ss, nil
s = append(s, transaction.Signer{
Account: c.notary.notary,
Scopes: transaction.None,
})
return s, nil
} }
func (c *Client) notaryAccounts(invokedByAlpha bool, multiaddr *wallet.Account) []*wallet.Account { func (c *Client) notaryAccounts(invokedByAlpha bool, multiaddr *wallet.Account) []*wallet.Account {