github.com/nspcc-dev/neo-go@v0.105.2-0.20240517133400-6be757af3eba/pkg/rpcclient/notary/contract_test.go (about) 1 package notary 2 3 import ( 4 "errors" 5 "math" 6 "math/big" 7 "strings" 8 "testing" 9 10 "github.com/nspcc-dev/neo-go/internal/testserdes" 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/util" 14 "github.com/nspcc-dev/neo-go/pkg/vm/stackitem" 15 "github.com/stretchr/testify/require" 16 ) 17 18 type testAct struct { 19 err error 20 res *result.Invoke 21 tx *transaction.Transaction 22 txh util.Uint256 23 vub uint32 24 } 25 26 func (t *testAct) Call(contract util.Uint160, operation string, params ...any) (*result.Invoke, error) { 27 return t.res, t.err 28 } 29 func (t *testAct) MakeRun(script []byte) (*transaction.Transaction, error) { 30 return t.tx, t.err 31 } 32 func (t *testAct) MakeUnsignedRun(script []byte, attrs []transaction.Attribute) (*transaction.Transaction, error) { 33 return t.tx, t.err 34 } 35 func (t *testAct) SendRun(script []byte) (util.Uint256, uint32, error) { 36 return t.txh, t.vub, t.err 37 } 38 func (t *testAct) MakeCall(contract util.Uint160, method string, params ...any) (*transaction.Transaction, error) { 39 return t.tx, t.err 40 } 41 func (t *testAct) MakeUnsignedCall(contract util.Uint160, method string, attrs []transaction.Attribute, params ...any) (*transaction.Transaction, error) { 42 return t.tx, t.err 43 } 44 func (t *testAct) SendCall(contract util.Uint160, method string, params ...any) (util.Uint256, uint32, error) { 45 return t.txh, t.vub, t.err 46 } 47 48 func TestBalanceOf(t *testing.T) { 49 ta := &testAct{} 50 ntr := NewReader(ta) 51 52 ta.err = errors.New("") 53 _, err := ntr.BalanceOf(util.Uint160{}) 54 require.Error(t, err) 55 56 ta.err = nil 57 ta.res = &result.Invoke{ 58 State: "HALT", 59 Stack: []stackitem.Item{ 60 stackitem.Make(42), 61 }, 62 } 63 res, err := ntr.BalanceOf(util.Uint160{}) 64 require.NoError(t, err) 65 require.Equal(t, big.NewInt(42), res) 66 } 67 68 func TestUint32Getters(t *testing.T) { 69 ta := &testAct{} 70 ntr := NewReader(ta) 71 72 for name, fun := range map[string]func() (uint32, error){ 73 "ExpirationOf": func() (uint32, error) { 74 return ntr.ExpirationOf(util.Uint160{1, 2, 3}) 75 }, 76 "GetMaxNotValidBeforeDelta": ntr.GetMaxNotValidBeforeDelta, 77 } { 78 t.Run(name, func(t *testing.T) { 79 ta.err = errors.New("") 80 _, err := fun() 81 require.Error(t, err) 82 83 ta.err = nil 84 ta.res = &result.Invoke{ 85 State: "HALT", 86 Stack: []stackitem.Item{ 87 stackitem.Make(42), 88 }, 89 } 90 res, err := fun() 91 require.NoError(t, err) 92 require.Equal(t, uint32(42), res) 93 94 ta.res = &result.Invoke{ 95 State: "HALT", 96 Stack: []stackitem.Item{ 97 stackitem.Make(-1), 98 }, 99 } 100 _, err = fun() 101 require.Error(t, err) 102 }) 103 } 104 } 105 106 func TestTxSenders(t *testing.T) { 107 ta := new(testAct) 108 ntr := New(ta) 109 110 for name, fun := range map[string]func() (util.Uint256, uint32, error){ 111 "LockDepositUntil": func() (util.Uint256, uint32, error) { 112 return ntr.LockDepositUntil(util.Uint160{1, 2, 3}, 100500) 113 }, 114 "SetMaxNotValidBeforeDelta": func() (util.Uint256, uint32, error) { 115 return ntr.SetMaxNotValidBeforeDelta(42) 116 }, 117 "Withdraw": func() (util.Uint256, uint32, error) { 118 return ntr.Withdraw(util.Uint160{1, 2, 3}, util.Uint160{3, 2, 1}) 119 }, 120 } { 121 t.Run(name, func(t *testing.T) { 122 ta.err = errors.New("") 123 _, _, err := fun() 124 require.Error(t, err) 125 126 ta.err = nil 127 ta.txh = util.Uint256{1, 2, 3} 128 ta.vub = 42 129 h, vub, err := fun() 130 require.NoError(t, err) 131 require.Equal(t, ta.txh, h) 132 require.Equal(t, ta.vub, vub) 133 }) 134 } 135 } 136 137 func TestTxMakers(t *testing.T) { 138 ta := new(testAct) 139 ntr := New(ta) 140 141 for name, fun := range map[string]func() (*transaction.Transaction, error){ 142 "LockDepositUntilTransaction": func() (*transaction.Transaction, error) { 143 return ntr.LockDepositUntilTransaction(util.Uint160{1, 2, 3}, 100500) 144 }, 145 "LockDepositUntilUnsigned": func() (*transaction.Transaction, error) { 146 return ntr.LockDepositUntilUnsigned(util.Uint160{1, 2, 3}, 100500) 147 }, 148 "SetMaxNotValidBeforeDeltaTransaction": func() (*transaction.Transaction, error) { 149 return ntr.SetMaxNotValidBeforeDeltaTransaction(42) 150 }, 151 "SetMaxNotValidBeforeDeltaUnsigned": func() (*transaction.Transaction, error) { 152 return ntr.SetMaxNotValidBeforeDeltaUnsigned(42) 153 }, 154 "WithdrawTransaction": func() (*transaction.Transaction, error) { 155 return ntr.WithdrawTransaction(util.Uint160{1, 2, 3}, util.Uint160{3, 2, 1}) 156 }, 157 "WithdrawUnsigned": func() (*transaction.Transaction, error) { 158 return ntr.WithdrawUnsigned(util.Uint160{1, 2, 3}, util.Uint160{3, 2, 1}) 159 }, 160 } { 161 t.Run(name, func(t *testing.T) { 162 ta.err = errors.New("") 163 _, err := fun() 164 require.Error(t, err) 165 166 ta.err = nil 167 ta.tx = &transaction.Transaction{Nonce: 100500, ValidUntilBlock: 42} 168 tx, err := fun() 169 require.NoError(t, err) 170 require.Equal(t, ta.tx, tx) 171 }) 172 } 173 } 174 175 func TestOnNEP17PaymentData_Convertible(t *testing.T) { 176 t.Run("non-empty owner", func(t *testing.T) { 177 d := &OnNEP17PaymentData{ 178 Account: &util.Uint160{1, 2, 3}, 179 Till: 123, 180 } 181 testserdes.ToFromStackItem(t, d, new(OnNEP17PaymentData)) 182 }) 183 t.Run("empty owner", func(t *testing.T) { 184 d := &OnNEP17PaymentData{ 185 Account: nil, 186 Till: 123, 187 } 188 testserdes.ToFromStackItem(t, d, new(OnNEP17PaymentData)) 189 }) 190 } 191 192 func TestOnNEP17PaymentDataToStackItem(t *testing.T) { 193 testCases := map[string]struct { 194 data *OnNEP17PaymentData 195 expected stackitem.Item 196 }{ 197 "non-empty owner": { 198 data: &OnNEP17PaymentData{ 199 Account: &util.Uint160{1, 2, 3}, 200 Till: 123, 201 }, 202 expected: stackitem.NewArray([]stackitem.Item{ 203 stackitem.Make(util.Uint160{1, 2, 3}), 204 stackitem.Make(123), 205 }), 206 }, 207 "empty owner": { 208 data: &OnNEP17PaymentData{ 209 Account: nil, 210 Till: 123, 211 }, 212 expected: stackitem.NewArray([]stackitem.Item{ 213 stackitem.Null{}, 214 stackitem.Make(123), 215 }), 216 }, 217 } 218 for name, tc := range testCases { 219 t.Run(name, func(t *testing.T) { 220 actual, err := tc.data.ToStackItem() 221 require.NoError(t, err) 222 require.Equal(t, tc.expected, actual) 223 }) 224 } 225 } 226 227 func TestOnNEP17PaymentData_FromStackItem(t *testing.T) { 228 errCases := map[string]stackitem.Item{ 229 "unexpected stackitem type": stackitem.NewBool(true), 230 "unexpected number of fields": stackitem.NewArray([]stackitem.Item{stackitem.NewBool(true)}), 231 "failed to retrieve account bytes": stackitem.NewArray([]stackitem.Item{stackitem.NewInterop(nil), stackitem.Make(1)}), 232 "failed to decode account bytes": stackitem.NewArray([]stackitem.Item{stackitem.Make([]byte{1}), stackitem.Make(1)}), 233 "failed to retrieve till": stackitem.NewArray([]stackitem.Item{stackitem.Make(util.Uint160{1}), stackitem.NewInterop(nil)}), 234 "till is not an int64": stackitem.NewArray([]stackitem.Item{stackitem.Make(util.Uint160{1}), stackitem.NewBigInteger(new(big.Int).Add(big.NewInt(math.MaxInt64), big.NewInt(1)))}), 235 "till is larger than max uint32 value": stackitem.NewArray([]stackitem.Item{stackitem.Make(util.Uint160{1}), stackitem.Make(math.MaxUint32 + 1)}), 236 } 237 for name, errCase := range errCases { 238 t.Run(name, func(t *testing.T) { 239 d := new(OnNEP17PaymentData) 240 err := d.FromStackItem(errCase) 241 require.Error(t, err) 242 require.True(t, strings.Contains(err.Error(), name), name) 243 }) 244 } 245 }