github.com/klaytn/klaytn@v1.10.2/tests/tx_gas_overflow_test.go (about) 1 // Copyright 2019 The klaytn Authors 2 // This file is part of the klaytn library. 3 // 4 // The klaytn library is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU Lesser General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // The klaytn library is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU Lesser General Public License for more details. 13 // 14 // You should have received a copy of the GNU Lesser General Public License 15 // along with the klaytn library. If not, see <http://www.gnu.org/licenses/>. 16 17 package tests 18 19 import ( 20 "testing" 21 22 "github.com/klaytn/klaytn/blockchain" 23 "github.com/klaytn/klaytn/blockchain/types" 24 "github.com/klaytn/klaytn/blockchain/types/accountkey" 25 "github.com/klaytn/klaytn/common/math" 26 "github.com/klaytn/klaytn/params" 27 ) 28 29 type overflowCheckFunc func(t *testing.T) 30 31 func TestGasOverflow(t *testing.T) { 32 testFunctions := []struct { 33 Name string 34 gasOverflowCheckFunc overflowCheckFunc 35 }{ 36 {"LegacyTransaction", testGasOverflowLegacyTransaction}, 37 38 {"ValueTransfer", testGasOverflowValueTransfer}, 39 {"FeeDelegatedValueTransfer", testGasOverflowFeeDelegatedValueTransfer}, 40 {"FeeDelegatedWithRatioValueTransfer", testGasOverflowFeeDelegatedWithRatioValueTransfer}, 41 42 {"ValueTransferWithMemo", testGasOverflowValueTransferWithMemo}, 43 {"FeeDelegatedValueTransferWithMemo", testGasOverflowFeeDelegatedValueTransferWithMemo}, 44 {"FeeDelegatedWithRatioValueTransferWithMemo", testGasOverflowFeeDelegatedWithRatioValueTransferWithMemo}, 45 46 {"AccountUpdate", testGasOverflowAccountUpdate}, 47 {"FeeDelegatedAccountUpdate", testGasOverflowFeeDelegatedAccountUpdate}, 48 {"FeeDelegatedWithRatioAccountUpdate", testGasOverflowFeeDelegatedWithRatioAccountUpdate}, 49 50 {"SmartContractDeploy", testGasOverflowSmartContractDeploy}, 51 {"FeeDelegatedSmartContractDeploy", testGasOverflowFeeDelegatedSmartContractDeploy}, 52 {"FeeDelegatedWithRatioSmartContractDeploy", testGasOverflowFeeDelegatedWithRatioSmartContractDeploy}, 53 54 {"SmartContractExecution", testGasOverflowSmartContractExecution}, 55 {"FeeDelegatedSmartContractExecution", testGasOverflowFeeDelegatedSmartContractExecution}, 56 {"FeeDelegatedWithRatioSmartContractExecution", testGasOverflowFeeDelegatedWithRatioSmartContractExecution}, 57 58 {"Cancel", testGasOverflowCancel}, 59 {"FeeDelegatedCancel", testGasOverflowFeeDelegatedCancel}, 60 {"FeeDelegatedWithRatioCancel", testGasOverflowFeeDelegatedWithRatioCancel}, 61 62 {"ChainDataAnchoring", testGasOverflowChainDataAnchoring}, 63 {"FeeDelegatedChainDataAnchoring", testGasOverflowFeeDelegatedChainDataAnchoring}, 64 {"FeeDelegatedWithRatioChainDataAnchoring", testGasOverflowFeeDelegatedWithRatioChainDataAnchoring}, 65 } 66 67 for _, f := range testFunctions { 68 t.Run(f.Name, func(t *testing.T) { 69 f.gasOverflowCheckFunc(t) 70 }) 71 } 72 } 73 74 func testGasOverflowLegacyTransaction(t *testing.T) { 75 intrinsic := getIntrinsicGas(types.TxTypeLegacyTransaction) 76 senderValidationGas := getMaxValidationKeyGas(t) 77 78 maxDataGas := mulUint64(t, blockchain.MaxTxDataSize, params.TxDataNonZeroGas) 79 80 gas := addUint64(t, intrinsic, senderValidationGas) 81 gas = addUint64(t, gas, maxDataGas) 82 } 83 84 func testGasOverflowValueTransfer(t *testing.T) { 85 intrinsic := getIntrinsicGas(types.TxTypeValueTransfer) 86 senderValidationGas := getMaxValidationKeyGas(t) 87 88 addUint64(t, intrinsic, senderValidationGas) 89 } 90 91 func testGasOverflowFeeDelegatedValueTransfer(t *testing.T) { 92 intrinsic := getIntrinsicGas(types.TxTypeFeeDelegatedValueTransfer) 93 senderValidationGas := getMaxValidationKeyGas(t) 94 payerValidationGas := getMaxValidationKeyGas(t) 95 96 gas := addUint64(t, intrinsic, senderValidationGas) 97 gas = addUint64(t, gas, payerValidationGas) 98 } 99 100 func testGasOverflowFeeDelegatedWithRatioValueTransfer(t *testing.T) { 101 intrinsic := getIntrinsicGas(types.TxTypeFeeDelegatedValueTransferWithRatio) 102 senderValidationGas := getMaxValidationKeyGas(t) 103 payerValidationGas := getMaxValidationKeyGas(t) 104 105 gas := addUint64(t, intrinsic, senderValidationGas) 106 gas = addUint64(t, gas, payerValidationGas) 107 } 108 109 func testGasOverflowValueTransferWithMemo(t *testing.T) { 110 intrinsic := getIntrinsicGas(types.TxTypeValueTransferMemo) 111 senderValidationGas := getMaxValidationKeyGas(t) 112 113 maxDataGas := mulUint64(t, blockchain.MaxTxDataSize, params.TxDataGas) 114 115 gas := addUint64(t, intrinsic, senderValidationGas) 116 gas = addUint64(t, gas, maxDataGas) 117 } 118 119 func testGasOverflowFeeDelegatedValueTransferWithMemo(t *testing.T) { 120 intrinsic := getIntrinsicGas(types.TxTypeFeeDelegatedValueTransferMemo) 121 senderValidationGas := getMaxValidationKeyGas(t) 122 payerValidationGas := getMaxValidationKeyGas(t) 123 124 maxDataGas := mulUint64(t, blockchain.MaxTxDataSize, params.TxDataGas) 125 126 gas := addUint64(t, intrinsic, senderValidationGas) 127 gas = addUint64(t, gas, payerValidationGas) 128 gas = addUint64(t, gas, maxDataGas) 129 } 130 131 func testGasOverflowFeeDelegatedWithRatioValueTransferWithMemo(t *testing.T) { 132 intrinsic := getIntrinsicGas(types.TxTypeFeeDelegatedValueTransferMemoWithRatio) 133 senderValidationGas := getMaxValidationKeyGas(t) 134 payerValidationGas := getMaxValidationKeyGas(t) 135 136 maxDataGas := mulUint64(t, blockchain.MaxTxDataSize, params.TxDataGas) 137 138 gas := addUint64(t, intrinsic, senderValidationGas) 139 gas = addUint64(t, gas, payerValidationGas) 140 gas = addUint64(t, gas, maxDataGas) 141 } 142 143 func testGasOverflowAccountUpdate(t *testing.T) { 144 intrinsic := getIntrinsicGas(types.TxTypeAccountUpdate) 145 senderValidationGas := getMaxValidationKeyGas(t) 146 147 maxCreationGas := getMaxCreationKeyGas(t) 148 149 gas := addUint64(t, intrinsic, senderValidationGas) 150 gas = addUint64(t, gas, maxCreationGas) 151 } 152 153 func testGasOverflowFeeDelegatedAccountUpdate(t *testing.T) { 154 intrinsic := getIntrinsicGas(types.TxTypeFeeDelegatedAccountUpdate) 155 senderValidationGas := getMaxValidationKeyGas(t) 156 payerValidationGas := getMaxValidationKeyGas(t) 157 158 maxCreationGas := getMaxCreationKeyGas(t) 159 160 gas := addUint64(t, intrinsic, senderValidationGas) 161 gas = addUint64(t, gas, payerValidationGas) 162 gas = addUint64(t, gas, maxCreationGas) 163 } 164 165 func testGasOverflowFeeDelegatedWithRatioAccountUpdate(t *testing.T) { 166 intrinsic := getIntrinsicGas(types.TxTypeFeeDelegatedAccountUpdateWithRatio) 167 senderValidationGas := getMaxValidationKeyGas(t) 168 payerValidationGas := getMaxValidationKeyGas(t) 169 170 maxCreationGas := getMaxCreationKeyGas(t) 171 172 gas := addUint64(t, intrinsic, senderValidationGas) 173 gas = addUint64(t, gas, payerValidationGas) 174 gas = addUint64(t, gas, maxCreationGas) 175 } 176 177 func testGasOverflowSmartContractDeploy(t *testing.T) { 178 intrinsic := getIntrinsicGas(types.TxTypeSmartContractDeploy) 179 senderValidationGas := getMaxValidationKeyGas(t) 180 181 payloadGas := mulUint64(t, blockchain.MaxTxDataSize, params.TxDataGas) 182 183 humanReadableGas := params.TxGasHumanReadable 184 185 gas := addUint64(t, intrinsic, senderValidationGas) 186 gas = addUint64(t, gas, payloadGas) 187 gas = addUint64(t, gas, humanReadableGas) 188 } 189 190 func testGasOverflowFeeDelegatedSmartContractDeploy(t *testing.T) { 191 intrinsic := getIntrinsicGas(types.TxTypeFeeDelegatedSmartContractDeploy) 192 senderValidationGas := getMaxValidationKeyGas(t) 193 payerValidationGas := getMaxValidationKeyGas(t) 194 195 payloadGas := mulUint64(t, blockchain.MaxTxDataSize, params.TxDataGas) 196 197 humanReadableGas := params.TxGasHumanReadable 198 199 gas := addUint64(t, intrinsic, senderValidationGas) 200 gas = addUint64(t, gas, payerValidationGas) 201 gas = addUint64(t, gas, payloadGas) 202 gas = addUint64(t, gas, humanReadableGas) 203 } 204 205 func testGasOverflowFeeDelegatedWithRatioSmartContractDeploy(t *testing.T) { 206 intrinsic := getIntrinsicGas(types.TxTypeFeeDelegatedSmartContractDeployWithRatio) 207 senderValidationGas := getMaxValidationKeyGas(t) 208 payerValidationGas := getMaxValidationKeyGas(t) 209 210 payloadGas := mulUint64(t, blockchain.MaxTxDataSize, params.TxDataGas) 211 212 humanReadableGas := params.TxGasHumanReadable 213 214 gas := addUint64(t, intrinsic, senderValidationGas) 215 gas = addUint64(t, gas, payerValidationGas) 216 gas = addUint64(t, gas, payloadGas) 217 gas = addUint64(t, gas, humanReadableGas) 218 } 219 220 func testGasOverflowSmartContractExecution(t *testing.T) { 221 intrinsic := getIntrinsicGas(types.TxTypeSmartContractExecution) 222 senderValidationGas := getMaxValidationKeyGas(t) 223 224 payloadGas := mulUint64(t, blockchain.MaxTxDataSize, params.TxDataGas) 225 226 gas := addUint64(t, intrinsic, senderValidationGas) 227 gas = addUint64(t, gas, payloadGas) 228 } 229 230 func testGasOverflowFeeDelegatedSmartContractExecution(t *testing.T) { 231 intrinsic := getIntrinsicGas(types.TxTypeFeeDelegatedSmartContractExecution) 232 senderValidationGas := getMaxValidationKeyGas(t) 233 payerValidationGas := getMaxValidationKeyGas(t) 234 235 payloadGas := mulUint64(t, blockchain.MaxTxDataSize, params.TxDataGas) 236 237 gas := addUint64(t, intrinsic, senderValidationGas) 238 gas = addUint64(t, gas, payerValidationGas) 239 gas = addUint64(t, gas, payloadGas) 240 } 241 242 func testGasOverflowFeeDelegatedWithRatioSmartContractExecution(t *testing.T) { 243 intrinsic := getIntrinsicGas(types.TxTypeFeeDelegatedSmartContractExecutionWithRatio) 244 senderValidationGas := getMaxValidationKeyGas(t) 245 payerValidationGas := getMaxValidationKeyGas(t) 246 247 payloadGas := mulUint64(t, blockchain.MaxTxDataSize, params.TxDataGas) 248 249 gas := addUint64(t, intrinsic, senderValidationGas) 250 gas = addUint64(t, gas, payerValidationGas) 251 gas = addUint64(t, gas, payloadGas) 252 } 253 254 func testGasOverflowCancel(t *testing.T) { 255 intrinsic := getIntrinsicGas(types.TxTypeCancel) 256 senderValidationGas := getMaxValidationKeyGas(t) 257 258 addUint64(t, intrinsic, senderValidationGas) 259 } 260 261 func testGasOverflowFeeDelegatedCancel(t *testing.T) { 262 intrinsic := getIntrinsicGas(types.TxTypeFeeDelegatedCancel) 263 senderValidationGas := getMaxValidationKeyGas(t) 264 payerValidationGas := getMaxValidationKeyGas(t) 265 266 gas := addUint64(t, intrinsic, senderValidationGas) 267 gas = addUint64(t, gas, payerValidationGas) 268 } 269 270 func testGasOverflowFeeDelegatedWithRatioCancel(t *testing.T) { 271 intrinsic := getIntrinsicGas(types.TxTypeFeeDelegatedCancelWithRatio) 272 senderValidationGas := getMaxValidationKeyGas(t) 273 payerValidationGas := getMaxValidationKeyGas(t) 274 275 gas := addUint64(t, intrinsic, senderValidationGas) 276 gas = addUint64(t, gas, payerValidationGas) 277 } 278 279 func testGasOverflowChainDataAnchoring(t *testing.T) { 280 intrinsic := getIntrinsicGas(types.TxTypeChainDataAnchoring) 281 senderValidationGas := getMaxValidationKeyGas(t) 282 283 maxDataGas := mulUint64(t, blockchain.MaxTxDataSize, params.TxDataGas) 284 285 gas := addUint64(t, intrinsic, senderValidationGas) 286 gas = addUint64(t, gas, maxDataGas) 287 } 288 289 func testGasOverflowFeeDelegatedChainDataAnchoring(t *testing.T) { 290 intrinsic := getIntrinsicGas(types.TxTypeFeeDelegatedChainDataAnchoring) 291 senderValidationGas := getMaxValidationKeyGas(t) 292 payerValidationGas := getMaxValidationKeyGas(t) 293 294 maxDataGas := mulUint64(t, blockchain.MaxTxDataSize, params.TxDataGas) 295 296 gas := addUint64(t, intrinsic, senderValidationGas) 297 gas = addUint64(t, gas, payerValidationGas) 298 gas = addUint64(t, gas, maxDataGas) 299 } 300 301 func testGasOverflowFeeDelegatedWithRatioChainDataAnchoring(t *testing.T) { 302 intrinsic := getIntrinsicGas(types.TxTypeFeeDelegatedChainDataAnchoringWithRatio) 303 senderValidationGas := getMaxValidationKeyGas(t) 304 payerValidationGas := getMaxValidationKeyGas(t) 305 306 maxDataGas := mulUint64(t, blockchain.MaxTxDataSize, params.TxDataGas) 307 308 gas := addUint64(t, intrinsic, senderValidationGas) 309 gas = addUint64(t, gas, payerValidationGas) 310 gas = addUint64(t, gas, maxDataGas) 311 } 312 313 func getMaxValidationKeyGas(t *testing.T) uint64 { 314 return mulUint64(t, uint64(accountkey.MaxNumKeysForMultiSig), params.TxValidationGasPerKey) 315 } 316 317 func getMaxCreationKeyGas(t *testing.T) uint64 { 318 txKeyGas := mulUint64(t, uint64(accountkey.MaxNumKeysForMultiSig), params.TxAccountCreationGasPerKey) 319 updateKeyGas := mulUint64(t, uint64(accountkey.MaxNumKeysForMultiSig), params.TxAccountCreationGasPerKey) 320 feeKeysGas := mulUint64(t, uint64(accountkey.MaxNumKeysForMultiSig), params.TxAccountCreationGasPerKey) 321 322 creationKey := addUint64(t, txKeyGas, updateKeyGas) 323 creationKey = addUint64(t, creationKey, feeKeysGas) 324 325 return creationKey 326 } 327 328 func addUint64(t *testing.T, a uint64, b uint64) uint64 { 329 c, overflow := math.SafeAdd(a, b) 330 if overflow { 331 t.Error("gas overflow ", a, "+", b) 332 } 333 return c 334 } 335 336 func mulUint64(t *testing.T, a uint64, b uint64) uint64 { 337 c, overflow := math.SafeMul(a, b) 338 if overflow { 339 t.Error("gas overflow ", a, "*", b) 340 } 341 return c 342 }