Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

core: move transaction sender to signers #1244

Merged
merged 5 commits into from
Aug 4, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 37 additions & 28 deletions cli/smartcontract/smart_contract.go
Original file line number Diff line number Diff line change
Expand Up @@ -148,26 +148,29 @@ func NewCommands() []cli.Command {
{
Name: "invokefunction",
Usage: "invoke deployed contract on the blockchain",
UsageText: "neo-go contract invokefunction -r endpoint -w wallet [-a address] [-g gas] scripthash [method] [arguments...] [--] [cosigners...]",
UsageText: "neo-go contract invokefunction -r endpoint -w wallet [-a address] [-g gas] scripthash [method] [arguments...] [--] [signers...]",
Description: `Executes given (as a script hash) deployed script with the given method,
arguments and cosigners. See testinvokefunction documentation for the details
about parameters. It differs from testinvokefunction in that this command
sends an invocation transaction to the network.
arguments and signers. Sender is included in the list of signers by default
with FeeOnly witness scope. If you'd like to change default sender's scope,
specify it via signers parameter. See testinvokefunction documentation for
the details about parameters. It differs from testinvokefunction in that this
command sends an invocation transaction to the network.
`,
Action: invokeFunction,
Flags: invokeFunctionFlags,
},
{
Name: "testinvokefunction",
Usage: "invoke deployed contract on the blockchain (test mode)",
UsageText: "neo-go contract testinvokefunction -r endpoint scripthash [method] [arguments...] [--] [cosigners...]",
UsageText: "neo-go contract testinvokefunction -r endpoint scripthash [method] [arguments...] [--] [signers...]",
Description: `Executes given (as a script hash) deployed script with the given method,
arguments and cosigners. If no method is given "" is passed to the script, if
no arguments are given, an empty array is passed, if no cosigners are given,
no array will be passed. All of the given arguments are encapsulated into
array before invoking the script. The script thus should follow the regular
convention of smart contract arguments (method string and an array of other
arguments).
arguments and signers (sender is not included by default). If no method is given
"" is passed to the script, if no arguments are given, an empty array is
passed, if no signers are given no array is passed. If signers are specified,
the first one of them is treated as a sender. All of the given arguments are
encapsulated into array before invoking the script. The script thus should
follow the regular convention of smart contract arguments (method string and
an array of other arguments).

Arguments always do have regular Neo smart contract parameter types, either
specified explicitly or being inferred from the value. To specify the type
Expand Down Expand Up @@ -224,12 +227,15 @@ func NewCommands() []cli.Command {
* '03b209fd4f53a7170ea4444e0cb0a6bb6a53c2bd016926989cf85f9b0fba17a70c' is a
key with a value of '03b209fd4f53a7170ea4444e0cb0a6bb6a53c2bd016926989cf85f9b0fba17a70c'

Cosigners represent a set of Uint160 hashes with witness scopes and are used
to verify hashes in System.Runtime.CheckWitness syscall. To specify cosigners
use cosigner[:scope] syntax where
* 'cosigner' is hex-encoded 160 bit (20 byte) LE value of cosigner's address,
Signers represent a set of Uint160 hashes with witness scopes and are used
to verify hashes in System.Runtime.CheckWitness syscall. First signer is treated
as a sender. To specify signers use signer[:scope] syntax where
* 'signer' is hex-encoded 160 bit (20 byte) LE value of signer's address,
fyrchik marked this conversation as resolved.
Show resolved Hide resolved
which could have '0x' prefix.
* 'scope' is a comma-separated set of cosigner's scopes, which could be:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We're missing FeeOnly scope here.

- 'FeeOnly' - marks transaction's sender and can be used only for the
sender. Signer with this scope can't be used during the
script execution and only pays fees for the transaction.
- 'Global' - allows this witness in all contexts. This cannot be combined
with other flags.
- 'CalledByEntry' - means that this condition must hold: EntryScriptHash
Expand All @@ -240,8 +246,8 @@ func NewCommands() []cli.Command {
- 'CustomContracts' - define valid custom contract hashes for witness check.
- 'CustomGroups' - define custom pubkey for group members.

If no scopes were specified, 'Global' used as default. If no cosigners were
specified, no array will be passed. Note that scopes are properly handled by
If no scopes were specified, 'Global' used as default. If no signers were
specified, no array is passed. Note that scopes are properly handled by
neo-go RPC server only. C# implementation does not support scopes capability.

Examples:
Expand All @@ -256,9 +262,10 @@ func NewCommands() []cli.Command {
{
Name: "testinvokescript",
Usage: "Invoke compiled AVM code in NEF format on the blockchain (test mode, not creating a transaction for it)",
UsageText: "neo-go contract testinvokescript -r endpoint -i input.nef [cosigners...]",
UsageText: "neo-go contract testinvokescript -r endpoint -i input.nef [signers...]",
Description: `Executes given compiled AVM instructions in NEF format with the given set of
cosigners. See testinvokefunction documentation for the details about parameters.
signers not included sender by default. See testinvokefunction documentation
for the details about parameters.
`,
Action: testInvokeScript,
Flags: testInvokeScriptFlags,
Expand Down Expand Up @@ -389,7 +396,7 @@ func invokeInternal(ctx *cli.Context, signAndPush bool) error {
operation string
params = make([]smartcontract.Parameter, 0)
paramsStart = 1
cosigners []transaction.Cosigner
cosigners []transaction.Signer
cosignersStart = 0
resp *result.Invoke
acc *wallet.Account
Expand Down Expand Up @@ -493,14 +500,14 @@ func testInvokeScript(ctx *cli.Context) error {
}

args := ctx.Args()
var cosigners []transaction.Cosigner
var signers []transaction.Signer
if args.Present() {
for i, c := range args[:] {
cosigner, err := parseCosigner(c)
if err != nil {
return cli.NewExitError(fmt.Errorf("failed to parse cosigner #%d: %v", i+1, err), 1)
return cli.NewExitError(fmt.Errorf("failed to parse signer #%d: %v", i+1, err), 1)
}
cosigners = append(cosigners, cosigner)
signers = append(signers, cosigner)
}
}

Expand All @@ -512,7 +519,7 @@ func testInvokeScript(ctx *cli.Context) error {
return err
}

resp, err := c.InvokeScript(nefFile.Script, cosigners)
resp, err := c.InvokeScript(nefFile.Script, signers)
if err != nil {
return cli.NewExitError(err, 1)
}
Expand Down Expand Up @@ -659,7 +666,7 @@ func contractDeploy(ctx *cli.Context) error {
if err != nil {
return cli.NewExitError(fmt.Errorf("failed to create deployment script: %v", err), 1)
}
// It doesn't require any cosigners.
// It doesn't require any signers.
invRes, err := c.InvokeScript(txScript, nil)
if err != nil {
return cli.NewExitError(fmt.Errorf("failed to test-invoke deployment script: %v", err), 1)
Expand Down Expand Up @@ -687,10 +694,12 @@ func parseContractConfig(confFile string) (ProjectConfig, error) {
return conf, nil
}

func parseCosigner(c string) (transaction.Cosigner, error) {
func parseCosigner(c string) (transaction.Signer, error) {
var (
err error
res = transaction.Cosigner{}
res = transaction.Signer{
Scopes: transaction.Global,
}
)
data := strings.SplitN(c, ":", 2)
s := data[0]
Expand All @@ -704,7 +713,7 @@ func parseCosigner(c string) (transaction.Cosigner, error) {
if len(data) > 1 {
res.Scopes, err = transaction.ScopesFromString(data[1])
if err != nil {
return transaction.Cosigner{}, err
return transaction.Signer{}, err
}
}
return res, nil
Expand Down
10 changes: 5 additions & 5 deletions docs/notifications.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ Currently supported events:
Filters: primary ID.
* new transaction in the block
Contents: transaction.
Filters: sender and cosigner.
Filters: sender and signer.
* notification generated during execution
Contents: container hash, contract script hash, stack item.
Filters: contract script hash.
Expand Down Expand Up @@ -57,8 +57,8 @@ Recognized stream names:
ConsensusData.
* `transaction_added`
Filter: `sender` field containing string with hex-encoded Uint160 (LE
representation) for transaction's `Sender` and/or `cosigner` in the same
format for one of transaction's `Cosigners`.
representation) for transaction's `Sender` and/or `signer` in the same
format for one of transaction's `Signers`.
* `notification_from_execution`
Filter: `contract` field containing string with hex-encoded Uint160 (LE
representation).
Expand Down Expand Up @@ -203,7 +203,7 @@ Example:
"sysfee" : "0",
"type" : "InvocationTransaction",
"nonce" : 9,
"cosigners" : [
"signers" : [
{
"scopes" : 1,
"account" : "0x870958fd19ee3f6c7dc3c2df399d013910856e31"
Expand Down Expand Up @@ -262,7 +262,7 @@ Example:
"nonce" : 9,
"vin" : [],
"type" : "InvocationTransaction",
"cosigners" : [
"signers" : [
{
"account" : "0x870958fd19ee3f6c7dc3c2df399d013910856e31",
"scopes" : 1
Expand Down
7 changes: 6 additions & 1 deletion integration/performance_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,12 @@ func getTX(t *testing.B, wif *keys.WIF) *transaction.Transaction {

tx := transaction.New(netmode.UnitTestNet, []byte{0x51}, 1)
tx.Version = 0
tx.Sender = fromAddressHash
tx.Signers = []transaction.Signer{
{
Account: fromAddressHash,
Scopes: transaction.FeeOnly,
},
}
tx.Attributes = append(tx.Attributes,
transaction.Attribute{
Usage: transaction.DescriptionURL,
Expand Down
6 changes: 5 additions & 1 deletion pkg/consensus/consensus_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,11 @@ var neoOwner = testchain.MultisigScriptHash()

func addSender(t *testing.T, txs ...*transaction.Transaction) {
for _, tx := range txs {
tx.Sender = neoOwner
tx.Signers = []transaction.Signer{
{
Account: neoOwner,
},
}
}
}

Expand Down
14 changes: 4 additions & 10 deletions pkg/core/blockchain.go
Original file line number Diff line number Diff line change
Expand Up @@ -1226,7 +1226,7 @@ func (bc *Blockchain) verifyTx(t *transaction.Transaction, block *block.Block) e
if maxBlockSystemFee < t.SystemFee {
return errors.Errorf("policy check failed: transaction's fee shouldn't exceed maximum block system fee %d", maxBlockSystemFee)
}
balance := bc.GetUtilityTokenBalance(t.Sender)
balance := bc.GetUtilityTokenBalance(t.Sender())
need := t.SystemFee + t.NetworkFee
if balance.Cmp(big.NewInt(need)) < 0 {
return errors.Errorf("insufficient funds: balance is %v, need: %v", balance, need)
Expand Down Expand Up @@ -1415,15 +1415,9 @@ func (bc *Blockchain) GetEnrollments() ([]state.Validator, error) {
// to verify whether the transaction is bonafide or not.
// Golang implementation of GetScriptHashesForVerifying method in C# (https://github.com/neo-project/neo/blob/master/neo/Network/P2P/Payloads/Transaction.cs#L190)
func (bc *Blockchain) GetScriptHashesForVerifying(t *transaction.Transaction) ([]util.Uint160, error) {
hashes := make(map[util.Uint160]bool)
hashes[t.Sender] = true
for _, c := range t.Cosigners {
hashes[c.Account] = true
}
// convert hashes to []util.Uint160
hashesResult := make([]util.Uint160, 0, len(hashes))
for h := range hashes {
hashesResult = append(hashesResult, h)
hashesResult := make([]util.Uint160, len(t.Signers))
for i, s := range t.Signers {
hashesResult[i] = s.Account
}

return hashesResult, nil
Expand Down
8 changes: 4 additions & 4 deletions pkg/core/blockchain_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ func TestGetHeader(t *testing.T) {
bc := newTestChain(t)
tx := transaction.New(netmode.UnitTestNet, []byte{byte(opcode.PUSH1)}, 0)
tx.ValidUntilBlock = bc.BlockHeight() + 1
assert.Nil(t, addSender(tx))
addSigners(tx)
assert.Nil(t, signTx(bc, tx))
block := bc.newBlock(tx)
err := bc.AddBlock(block)
Expand Down Expand Up @@ -276,7 +276,7 @@ func TestSubscriptions(t *testing.T) {
emit.Syscall(script.BinWriter, "System.Runtime.Notify")
require.NoError(t, script.Err)
txGood1 := transaction.New(netmode.UnitTestNet, script.Bytes(), 0)
txGood1.Sender = neoOwner
txGood1.Signers = []transaction.Signer{{Account: neoOwner}}
txGood1.Nonce = 1
txGood1.ValidUntilBlock = 100500
require.NoError(t, signTx(bc, txGood1))
Expand All @@ -288,7 +288,7 @@ func TestSubscriptions(t *testing.T) {
emit.Opcode(script.BinWriter, opcode.THROW)
require.NoError(t, script.Err)
txBad := transaction.New(netmode.UnitTestNet, script.Bytes(), 0)
txBad.Sender = neoOwner
txBad.Signers = []transaction.Signer{{Account: neoOwner}}
txBad.Nonce = 2
txBad.ValidUntilBlock = 100500
require.NoError(t, signTx(bc, txBad))
Expand All @@ -298,7 +298,7 @@ func TestSubscriptions(t *testing.T) {
emit.Syscall(script.BinWriter, "System.Runtime.Notify")
require.NoError(t, script.Err)
txGood2 := transaction.New(netmode.UnitTestNet, script.Bytes(), 0)
txGood2.Sender = neoOwner
txGood2.Signers = []transaction.Signer{{Account: neoOwner}}
txGood2.Nonce = 3
txGood2.ValidUntilBlock = 100500
require.NoError(t, signTx(bc, txGood2))
Expand Down
Loading