github.com/nspcc-dev/neo-go@v0.105.2-0.20240517133400-6be757af3eba/pkg/rpcclient/actor/actor_test.go (about) 1 package actor 2 3 import ( 4 "context" 5 "errors" 6 "sync/atomic" 7 "testing" 8 9 "github.com/google/uuid" 10 "github.com/nspcc-dev/neo-go/pkg/config/netmode" 11 "github.com/nspcc-dev/neo-go/pkg/core/transaction" 12 "github.com/nspcc-dev/neo-go/pkg/neorpc/result" 13 "github.com/nspcc-dev/neo-go/pkg/smartcontract" 14 "github.com/nspcc-dev/neo-go/pkg/smartcontract/trigger" 15 "github.com/nspcc-dev/neo-go/pkg/util" 16 "github.com/nspcc-dev/neo-go/pkg/vm/stackitem" 17 "github.com/nspcc-dev/neo-go/pkg/wallet" 18 "github.com/stretchr/testify/require" 19 ) 20 21 type RPCClient struct { 22 err error 23 invRes *result.Invoke 24 netFee int64 25 bCount atomic.Uint32 26 version *result.Version 27 hash util.Uint256 28 appLog *result.ApplicationLog 29 context context.Context 30 } 31 32 func (r *RPCClient) InvokeContractVerify(contract util.Uint160, params []smartcontract.Parameter, signers []transaction.Signer, witnesses ...transaction.Witness) (*result.Invoke, error) { 33 return r.invRes, r.err 34 } 35 func (r *RPCClient) InvokeFunction(contract util.Uint160, operation string, params []smartcontract.Parameter, signers []transaction.Signer) (*result.Invoke, error) { 36 return r.invRes, r.err 37 } 38 func (r *RPCClient) InvokeScript(script []byte, signers []transaction.Signer) (*result.Invoke, error) { 39 return r.invRes, r.err 40 } 41 func (r *RPCClient) CalculateNetworkFee(tx *transaction.Transaction) (int64, error) { 42 return r.netFee, r.err 43 } 44 func (r *RPCClient) GetBlockCount() (uint32, error) { 45 return r.bCount.Load(), r.err 46 } 47 func (r *RPCClient) GetVersion() (*result.Version, error) { 48 verCopy := *r.version 49 return &verCopy, r.err 50 } 51 func (r *RPCClient) SendRawTransaction(tx *transaction.Transaction) (util.Uint256, error) { 52 return r.hash, r.err 53 } 54 func (r *RPCClient) TerminateSession(sessionID uuid.UUID) (bool, error) { 55 return false, nil // Just a stub, unused by actor. 56 } 57 func (r *RPCClient) TraverseIterator(sessionID, iteratorID uuid.UUID, maxItemsCount int) ([]stackitem.Item, error) { 58 return nil, nil // Just a stub, unused by actor. 59 } 60 func (r *RPCClient) Context() context.Context { 61 if r.context == nil { 62 return context.Background() 63 } 64 return r.context 65 } 66 67 func (r *RPCClient) GetApplicationLog(hash util.Uint256, trig *trigger.Type) (*result.ApplicationLog, error) { 68 if r.appLog != nil { 69 return r.appLog, nil 70 } 71 return nil, errors.New("not found") 72 } 73 func testRPCAndAccount(t *testing.T) (*RPCClient, *wallet.Account) { 74 client := &RPCClient{ 75 version: &result.Version{ 76 Protocol: result.Protocol{ 77 Network: netmode.UnitTestNet, 78 MillisecondsPerBlock: 1000, 79 ValidatorsCount: 7, 80 }, 81 }, 82 } 83 acc, err := wallet.NewAccount() 84 require.NoError(t, err) 85 return client, acc 86 } 87 88 func TestNew(t *testing.T) { 89 client, acc := testRPCAndAccount(t) 90 91 // No signers. 92 _, err := New(client, nil) 93 require.Error(t, err) 94 95 _, err = New(client, []SignerAccount{}) 96 require.Error(t, err) 97 98 _, err = NewTuned(client, []SignerAccount{}, NewDefaultOptions()) 99 require.Error(t, err) 100 101 // Good simple. 102 a, err := NewSimple(client, acc) 103 require.NoError(t, err) 104 require.Equal(t, 1, len(a.signers)) 105 require.Equal(t, 1, len(a.txSigners)) 106 require.Equal(t, transaction.CalledByEntry, a.signers[0].Signer.Scopes) 107 require.Equal(t, transaction.CalledByEntry, a.txSigners[0].Scopes) 108 109 // Contractless account. 110 badAcc, err := wallet.NewAccount() 111 require.NoError(t, err) 112 badAccHash := badAcc.Contract.ScriptHash() 113 badAcc.Contract = nil 114 115 signers := []SignerAccount{{ 116 Signer: transaction.Signer{ 117 Account: acc.Contract.ScriptHash(), 118 Scopes: transaction.None, 119 }, 120 Account: acc, 121 }, { 122 Signer: transaction.Signer{ 123 Account: badAccHash, 124 Scopes: transaction.CalledByEntry, 125 }, 126 Account: badAcc, 127 }} 128 129 _, err = New(client, signers) 130 require.Error(t, err) 131 132 // GetVersion returning error. 133 client.err = errors.New("bad") 134 _, err = NewSimple(client, acc) 135 require.Error(t, err) 136 client.err = nil 137 138 // Account mismatch. 139 acc2, err := wallet.NewAccount() 140 require.NoError(t, err) 141 signers = []SignerAccount{{ 142 Signer: transaction.Signer{ 143 Account: acc2.Contract.ScriptHash(), 144 Scopes: transaction.None, 145 }, 146 Account: acc, 147 }, { 148 Signer: transaction.Signer{ 149 Account: acc2.Contract.ScriptHash(), 150 Scopes: transaction.CalledByEntry, 151 }, 152 Account: acc2, 153 }} 154 _, err = New(client, signers) 155 require.Error(t, err) 156 157 // Good multiaccount. 158 signers[0].Signer.Account = acc.Contract.ScriptHash() 159 a, err = New(client, signers) 160 require.NoError(t, err) 161 require.Equal(t, 2, len(a.signers)) 162 require.Equal(t, 2, len(a.txSigners)) 163 164 // Good tuned 165 opts := Options{ 166 Attributes: []transaction.Attribute{{Type: transaction.HighPriority}}, 167 } 168 a, err = NewTuned(client, signers, opts) 169 require.NoError(t, err) 170 require.Equal(t, 1, len(a.opts.Attributes)) 171 } 172 173 func TestSimpleWrappers(t *testing.T) { 174 client, acc := testRPCAndAccount(t) 175 origVer := *client.version 176 177 a, err := NewSimple(client, acc) 178 require.NoError(t, err) 179 180 client.netFee = 42 181 nf, err := a.CalculateNetworkFee(new(transaction.Transaction)) 182 require.NoError(t, err) 183 require.Equal(t, int64(42), nf) 184 185 client.bCount.Store(100500) 186 bc, err := a.GetBlockCount() 187 require.NoError(t, err) 188 require.Equal(t, uint32(100500), bc) 189 190 require.Equal(t, netmode.UnitTestNet, a.GetNetwork()) 191 client.version.Protocol.Network = netmode.TestNet 192 require.Equal(t, netmode.UnitTestNet, a.GetNetwork()) 193 require.Equal(t, origVer, a.GetVersion()) 194 195 a, err = NewSimple(client, acc) 196 require.NoError(t, err) 197 require.Equal(t, netmode.TestNet, a.GetNetwork()) 198 require.Equal(t, *client.version, a.GetVersion()) 199 200 client.hash = util.Uint256{1, 2, 3} 201 h, vub, err := a.Send(&transaction.Transaction{ValidUntilBlock: 123}) 202 require.NoError(t, err) 203 require.Equal(t, client.hash, h) 204 require.Equal(t, uint32(123), vub) 205 } 206 207 func TestSign(t *testing.T) { 208 client, acc := testRPCAndAccount(t) 209 acc2, err := wallet.NewAccount() 210 require.NoError(t, err) 211 212 a, err := New(client, []SignerAccount{{ 213 Signer: transaction.Signer{ 214 Account: acc.Contract.ScriptHash(), 215 Scopes: transaction.None, 216 }, 217 Account: acc, 218 }, { 219 Signer: transaction.Signer{ 220 Account: acc2.Contract.ScriptHash(), 221 Scopes: transaction.CalledByEntry, 222 }, 223 Account: &wallet.Account{ // Looks like acc2, but has no private key. 224 Address: acc2.Address, 225 EncryptedWIF: acc2.EncryptedWIF, 226 Contract: acc2.Contract, 227 }, 228 }}) 229 require.NoError(t, err) 230 231 script := []byte{1, 2, 3} 232 client.hash = util.Uint256{2, 5, 6} 233 client.invRes = &result.Invoke{State: "HALT", GasConsumed: 3, Script: script} 234 235 tx, err := a.MakeUnsignedRun(script, nil) 236 require.NoError(t, err) 237 require.Error(t, a.Sign(tx)) 238 _, _, err = a.SignAndSend(tx) 239 require.Error(t, err) 240 } 241 242 func TestSenders(t *testing.T) { 243 client, acc := testRPCAndAccount(t) 244 a, err := NewSimple(client, acc) 245 require.NoError(t, err) 246 script := []byte{1, 2, 3} 247 248 // Bad. 249 client.invRes = &result.Invoke{State: "FAULT", GasConsumed: 3, Script: script} 250 _, _, err = a.SendCall(util.Uint160{1}, "method", 42) 251 require.Error(t, err) 252 _, _, err = a.SendTunedCall(util.Uint160{1}, "method", nil, nil, 42) 253 require.Error(t, err) 254 _, _, err = a.SendRun(script) 255 require.Error(t, err) 256 _, _, err = a.SendTunedRun(script, nil, nil) 257 require.Error(t, err) 258 _, _, err = a.SendUncheckedRun(script, 1, nil, func(t *transaction.Transaction) error { 259 return errors.New("bad") 260 }) 261 require.Error(t, err) 262 263 // Good. 264 client.hash = util.Uint256{2, 5, 6} 265 client.invRes = &result.Invoke{State: "HALT", GasConsumed: 3, Script: script} 266 h, vub, err := a.SendCall(util.Uint160{1}, "method", 42) 267 require.NoError(t, err) 268 require.Equal(t, client.hash, h) 269 require.Equal(t, uint32(8), vub) 270 271 h, vub, err = a.SendTunedCall(util.Uint160{1}, "method", nil, nil, 42) 272 require.NoError(t, err) 273 require.Equal(t, client.hash, h) 274 require.Equal(t, uint32(8), vub) 275 276 h, vub, err = a.SendRun(script) 277 require.NoError(t, err) 278 require.Equal(t, client.hash, h) 279 require.Equal(t, uint32(8), vub) 280 281 h, vub, err = a.SendTunedRun(script, nil, nil) 282 require.NoError(t, err) 283 require.Equal(t, client.hash, h) 284 require.Equal(t, uint32(8), vub) 285 286 h, vub, err = a.SendUncheckedRun(script, 1, nil, nil) 287 require.NoError(t, err) 288 require.Equal(t, client.hash, h) 289 require.Equal(t, uint32(8), vub) 290 } 291 292 func TestSender(t *testing.T) { 293 client, acc := testRPCAndAccount(t) 294 a, err := NewSimple(client, acc) 295 require.NoError(t, err) 296 require.Equal(t, acc.ScriptHash(), a.Sender()) 297 }