2020-11-27 10:55:48 +00:00
package payload
import (
"testing"
"github.com/nspcc-dev/neo-go/internal/random"
"github.com/nspcc-dev/neo-go/pkg/core/transaction"
2022-10-05 07:45:52 +00:00
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
2020-11-27 10:55:48 +00:00
"github.com/nspcc-dev/neo-go/pkg/util"
"github.com/nspcc-dev/neo-go/pkg/vm/opcode"
"github.com/stretchr/testify/require"
)
func TestNotaryRequestIsValid ( t * testing . T ) {
mainTx := & transaction . Transaction {
Attributes : [ ] transaction . Attribute { { Type : transaction . NotaryAssistedT , Value : & transaction . NotaryAssisted { NKeys : 1 } } } ,
Script : [ ] byte { 0 , 1 , 2 } ,
ValidUntilBlock : 123 ,
}
2024-08-24 09:52:30 +00:00
emptySingleInvocation := append ( [ ] byte { byte ( opcode . PUSHDATA1 ) , keys . SignatureLen } , make ( [ ] byte , keys . SignatureLen ) ... )
2020-11-27 10:55:48 +00:00
errorCases := map [ string ] * P2PNotaryRequest {
"main tx: missing NotaryAssisted attribute" : { MainTransaction : & transaction . Transaction { } } ,
"main tx: zero NKeys" : { MainTransaction : & transaction . Transaction { Attributes : [ ] transaction . Attribute { { Type : transaction . NotaryAssistedT , Value : & transaction . NotaryAssisted { NKeys : 0 } } } } } ,
"fallback transaction: invalid signers count" : {
MainTransaction : mainTx ,
FallbackTransaction : & transaction . Transaction { Signers : [ ] transaction . Signer { { Account : random . Uint160 ( ) } } } ,
} ,
"fallback transaction: invalid witnesses count" : {
MainTransaction : mainTx ,
FallbackTransaction : & transaction . Transaction { Signers : [ ] transaction . Signer { { Account : random . Uint160 ( ) } } } ,
} ,
"fallback tx: invalid dummy Notary witness (bad witnesses length)" : {
MainTransaction : mainTx ,
FallbackTransaction : & transaction . Transaction {
Signers : [ ] transaction . Signer { { Account : random . Uint160 ( ) } , { Account : random . Uint160 ( ) } } ,
Scripts : [ ] transaction . Witness { { } } ,
} ,
} ,
"fallback tx: invalid dummy Notary witness (bad invocation script length)" : {
MainTransaction : mainTx ,
FallbackTransaction : & transaction . Transaction {
Signers : [ ] transaction . Signer { { Account : random . Uint160 ( ) } , { Account : random . Uint160 ( ) } } ,
Scripts : [ ] transaction . Witness { { } , { } } ,
} ,
} ,
"fallback tx: invalid dummy Notary witness (bad invocation script prefix)" : {
MainTransaction : mainTx ,
FallbackTransaction : & transaction . Transaction {
Signers : [ ] transaction . Signer { { Account : random . Uint160 ( ) } , { Account : random . Uint160 ( ) } } ,
2022-10-05 07:45:52 +00:00
Scripts : [ ] transaction . Witness { { InvocationScript : append ( [ ] byte { byte ( opcode . PUSHDATA1 ) , 65 } , make ( [ ] byte , keys . SignatureLen ) ... ) } , { } } ,
2020-11-27 10:55:48 +00:00
} ,
} ,
"fallback tx: invalid dummy Notary witness (non-empty verification script))" : {
MainTransaction : mainTx ,
FallbackTransaction : & transaction . Transaction {
Signers : [ ] transaction . Signer { { Account : random . Uint160 ( ) } , { Account : random . Uint160 ( ) } } ,
2024-08-24 09:52:30 +00:00
Scripts : [ ] transaction . Witness { { InvocationScript : emptySingleInvocation , VerificationScript : make ( [ ] byte , 1 ) } , { } } ,
2020-11-27 10:55:48 +00:00
} ,
} ,
"fallback tx: missing NotValidBefore attribute" : {
MainTransaction : mainTx ,
FallbackTransaction : & transaction . Transaction {
Signers : [ ] transaction . Signer { { Account : random . Uint160 ( ) } , { Account : random . Uint160 ( ) } } ,
2024-08-24 09:52:30 +00:00
Scripts : [ ] transaction . Witness { { InvocationScript : emptySingleInvocation , VerificationScript : make ( [ ] byte , 0 ) } , { } } ,
2020-11-27 10:55:48 +00:00
} ,
} ,
"fallback tx: invalid number of Conflicts attributes" : {
MainTransaction : mainTx ,
FallbackTransaction : & transaction . Transaction {
Attributes : [ ] transaction . Attribute { { Type : transaction . NotValidBeforeT , Value : & transaction . NotValidBefore { Height : 123 } } } ,
Signers : [ ] transaction . Signer { { Account : random . Uint160 ( ) } , { Account : random . Uint160 ( ) } } ,
2024-08-24 09:52:30 +00:00
Scripts : [ ] transaction . Witness { { InvocationScript : emptySingleInvocation , VerificationScript : make ( [ ] byte , 0 ) } , { } } ,
2020-11-27 10:55:48 +00:00
} ,
} ,
"fallback tx: does not conflicts with main tx" : {
MainTransaction : mainTx ,
FallbackTransaction : & transaction . Transaction {
Attributes : [ ] transaction . Attribute {
{ Type : transaction . NotValidBeforeT , Value : & transaction . NotValidBefore { Height : 123 } } ,
{ Type : transaction . ConflictsT , Value : & transaction . Conflicts { Hash : util . Uint256 { } } } ,
} ,
Signers : [ ] transaction . Signer { { Account : random . Uint160 ( ) } , { Account : random . Uint160 ( ) } } ,
2024-08-24 09:52:30 +00:00
Scripts : [ ] transaction . Witness { { InvocationScript : emptySingleInvocation , VerificationScript : make ( [ ] byte , 0 ) } , { } } ,
2020-11-27 10:55:48 +00:00
} ,
} ,
"fallback tx: missing NotaryAssisted attribute" : {
MainTransaction : mainTx ,
FallbackTransaction : & transaction . Transaction {
Attributes : [ ] transaction . Attribute {
{ Type : transaction . NotValidBeforeT , Value : & transaction . NotValidBefore { Height : 123 } } ,
{ Type : transaction . ConflictsT , Value : & transaction . Conflicts { Hash : mainTx . Hash ( ) } } ,
} ,
Signers : [ ] transaction . Signer { { Account : random . Uint160 ( ) } , { Account : random . Uint160 ( ) } } ,
2024-08-24 09:52:30 +00:00
Scripts : [ ] transaction . Witness { { InvocationScript : emptySingleInvocation , VerificationScript : make ( [ ] byte , 0 ) } , { } } ,
2020-11-27 10:55:48 +00:00
} ,
} ,
"fallback tx: non-zero NKeys" : {
MainTransaction : mainTx ,
FallbackTransaction : & transaction . Transaction {
Attributes : [ ] transaction . Attribute {
{ Type : transaction . NotValidBeforeT , Value : & transaction . NotValidBefore { Height : 123 } } ,
{ Type : transaction . ConflictsT , Value : & transaction . Conflicts { Hash : mainTx . Hash ( ) } } ,
{ Type : transaction . NotaryAssistedT , Value : & transaction . NotaryAssisted { NKeys : 1 } } ,
} ,
Signers : [ ] transaction . Signer { { Account : random . Uint160 ( ) } , { Account : random . Uint160 ( ) } } ,
2024-08-24 09:52:30 +00:00
Scripts : [ ] transaction . Witness { { InvocationScript : emptySingleInvocation , VerificationScript : make ( [ ] byte , 0 ) } , { } } ,
2020-11-27 10:55:48 +00:00
} ,
} ,
"fallback tx: ValidUntilBlock mismatch" : {
MainTransaction : mainTx ,
FallbackTransaction : & transaction . Transaction {
ValidUntilBlock : 321 ,
Attributes : [ ] transaction . Attribute {
{ Type : transaction . NotValidBeforeT , Value : & transaction . NotValidBefore { Height : 123 } } ,
{ Type : transaction . ConflictsT , Value : & transaction . Conflicts { Hash : mainTx . Hash ( ) } } ,
{ Type : transaction . NotaryAssistedT , Value : & transaction . NotaryAssisted { NKeys : 0 } } ,
} ,
Signers : [ ] transaction . Signer { { Account : random . Uint160 ( ) } , { Account : random . Uint160 ( ) } } ,
2024-08-24 09:52:30 +00:00
Scripts : [ ] transaction . Witness { { InvocationScript : emptySingleInvocation , VerificationScript : make ( [ ] byte , 0 ) } , { } } ,
2020-11-27 10:55:48 +00:00
} ,
} ,
}
for name , errCase := range errorCases {
t . Run ( name , func ( t * testing . T ) {
require . Error ( t , errCase . isValid ( ) )
} )
}
t . Run ( "good" , func ( t * testing . T ) {
p := & P2PNotaryRequest {
MainTransaction : mainTx ,
FallbackTransaction : & transaction . Transaction {
ValidUntilBlock : 123 ,
Attributes : [ ] transaction . Attribute {
{ Type : transaction . NotValidBeforeT , Value : & transaction . NotValidBefore { Height : 123 } } ,
{ Type : transaction . ConflictsT , Value : & transaction . Conflicts { Hash : mainTx . Hash ( ) } } ,
{ Type : transaction . NotaryAssistedT , Value : & transaction . NotaryAssisted { NKeys : 0 } } ,
} ,
Signers : [ ] transaction . Signer { { Account : random . Uint160 ( ) } , { Account : random . Uint160 ( ) } } ,
2024-08-24 09:52:30 +00:00
Scripts : [ ] transaction . Witness { { InvocationScript : emptySingleInvocation , VerificationScript : make ( [ ] byte , 0 ) } , { } } ,
2020-11-27 10:55:48 +00:00
} ,
}
require . NoError ( t , p . isValid ( ) )
} )
}
2021-02-08 09:26:02 +00:00
func TestNotaryRequestBytesFromBytes ( t * testing . T ) {
2020-11-27 10:55:48 +00:00
mainTx := & transaction . Transaction {
Attributes : [ ] transaction . Attribute { { Type : transaction . NotaryAssistedT , Value : & transaction . NotaryAssisted { NKeys : 1 } } } ,
Script : [ ] byte { 0 , 1 , 2 } ,
ValidUntilBlock : 123 ,
Signers : [ ] transaction . Signer { { Account : util . Uint160 { 1 , 5 , 9 } } } ,
Scripts : [ ] transaction . Witness { {
InvocationScript : [ ] byte { 1 , 4 , 7 } ,
VerificationScript : [ ] byte { 3 , 6 , 9 } ,
} } ,
}
_ = mainTx . Hash ( )
_ = mainTx . Size ( )
fallbackTx := & transaction . Transaction {
Script : [ ] byte { 3 , 2 , 1 } ,
ValidUntilBlock : 123 ,
Attributes : [ ] transaction . Attribute {
{ Type : transaction . NotValidBeforeT , Value : & transaction . NotValidBefore { Height : 123 } } ,
{ Type : transaction . ConflictsT , Value : & transaction . Conflicts { Hash : mainTx . Hash ( ) } } ,
{ Type : transaction . NotaryAssistedT , Value : & transaction . NotaryAssisted { NKeys : 0 } } ,
} ,
Signers : [ ] transaction . Signer { { Account : util . Uint160 { 1 , 4 , 7 } } , { Account : util . Uint160 { 9 , 8 , 7 } } } ,
Scripts : [ ] transaction . Witness {
2022-10-05 07:45:52 +00:00
{ InvocationScript : append ( [ ] byte { byte ( opcode . PUSHDATA1 ) , keys . SignatureLen } , make ( [ ] byte , keys . SignatureLen ) ... ) , VerificationScript : make ( [ ] byte , 0 ) } ,
2020-11-27 10:55:48 +00:00
{ InvocationScript : [ ] byte { 1 , 2 , 3 } , VerificationScript : [ ] byte { 1 , 2 , 3 } } } ,
}
_ = fallbackTx . Hash ( )
_ = fallbackTx . Size ( )
p := & P2PNotaryRequest {
MainTransaction : mainTx ,
FallbackTransaction : fallbackTx ,
Witness : transaction . Witness {
InvocationScript : [ ] byte { 1 , 2 , 3 } ,
VerificationScript : [ ] byte { 7 , 8 , 9 } ,
} ,
}
2021-02-08 09:26:02 +00:00
2021-03-12 11:14:22 +00:00
_ = p . Hash ( ) // initialize hash caches
2021-02-08 09:26:02 +00:00
bytes , err := p . Bytes ( )
require . NoError ( t , err )
2021-03-25 19:18:47 +00:00
actual , err := NewP2PNotaryRequestFromBytes ( bytes )
2021-02-08 09:26:02 +00:00
require . NoError ( t , err )
require . Equal ( t , p , actual )
2020-11-27 10:55:48 +00:00
}
2024-04-27 17:16:05 +00:00
func TestP2PNotaryRequest_Copy ( t * testing . T ) {
priv , err := keys . NewPrivateKey ( )
require . NoError ( t , err )
orig := & P2PNotaryRequest {
MainTransaction : & transaction . Transaction {
NetworkFee : 2000 ,
SystemFee : 500 ,
Nonce : 12345678 ,
ValidUntilBlock : 100 ,
Version : 1 ,
Signers : [ ] transaction . Signer {
{ Account : random . Uint160 ( ) , Scopes : transaction . Global , AllowedContracts : [ ] util . Uint160 { random . Uint160 ( ) } , AllowedGroups : keys . PublicKeys { priv . PublicKey ( ) } , Rules : [ ] transaction . WitnessRule { { Action : 0x01 , Condition : transaction . ConditionCalledByEntry { } } } } ,
{ Account : random . Uint160 ( ) , Scopes : transaction . CalledByEntry } ,
} ,
Attributes : [ ] transaction . Attribute {
{ Type : transaction . HighPriority , Value : & transaction . OracleResponse {
ID : 0 ,
Code : transaction . Success ,
Result : [ ] byte { 4 , 8 , 15 , 16 , 23 , 42 } ,
} } ,
} ,
Scripts : [ ] transaction . Witness {
{
InvocationScript : [ ] byte { 0x04 , 0x05 } ,
VerificationScript : [ ] byte { 0x06 , 0x07 } ,
} ,
} } ,
FallbackTransaction : & transaction . Transaction {
Version : 2 ,
SystemFee : 200 ,
NetworkFee : 100 ,
Script : [ ] byte { 3 , 2 , 1 } ,
Signers : [ ] transaction . Signer { { Account : util . Uint160 { 4 , 5 , 6 } } } ,
Attributes : [ ] transaction . Attribute { { Type : transaction . NotValidBeforeT } } ,
Scripts : [ ] transaction . Witness {
{
InvocationScript : [ ] byte { 0x0D , 0x0E } ,
VerificationScript : [ ] byte { 0x0F , 0x10 } ,
} ,
} ,
} ,
Witness : transaction . Witness {
InvocationScript : [ ] byte { 0x11 , 0x12 } ,
VerificationScript : [ ] byte { 0x13 , 0x14 } ,
} ,
}
p2pCopy := orig . Copy ( )
require . Equal ( t , orig , p2pCopy )
require . NotSame ( t , orig , p2pCopy )
require . Equal ( t , orig . MainTransaction , p2pCopy . MainTransaction )
require . Equal ( t , orig . FallbackTransaction , p2pCopy . FallbackTransaction )
require . Equal ( t , orig . Witness , p2pCopy . Witness )
p2pCopy . MainTransaction . Version = 3
p2pCopy . FallbackTransaction . Script [ 0 ] = 0x1F
p2pCopy . Witness . VerificationScript [ 1 ] = 0x22
require . NotEqual ( t , orig . MainTransaction . Version , p2pCopy . MainTransaction . Version )
require . NotEqual ( t , orig . FallbackTransaction . Script [ 0 ] , p2pCopy . FallbackTransaction . Script [ 0 ] )
require . NotEqual ( t , orig . Witness . VerificationScript [ 1 ] , p2pCopy . Witness . VerificationScript [ 1 ] )
}