code.vegaprotocol.io/vega@v0.79.0/core/processor/tx.go (about) 1 // Copyright (C) 2023 Gobalsky Labs Limited 2 // 3 // This program is free software: you can redistribute it and/or modify 4 // it under the terms of the GNU Affero General Public License as 5 // published by the Free Software Foundation, either version 3 of the 6 // License, or (at your option) any later version. 7 // 8 // This program is distributed in the hope that it will be useful, 9 // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 // GNU Affero General Public License for more details. 12 // 13 // You should have received a copy of the GNU Affero General Public License 14 // along with this program. If not, see <http://www.gnu.org/licenses/>. 15 16 package processor 17 18 import ( 19 "encoding/hex" 20 "errors" 21 "fmt" 22 23 "code.vegaprotocol.io/vega/commands" 24 "code.vegaprotocol.io/vega/core/txn" 25 "code.vegaprotocol.io/vega/libs/proto" 26 commandspb "code.vegaprotocol.io/vega/protos/vega/commands/v1" 27 28 "github.com/cometbft/cometbft/crypto/tmhash" 29 ) 30 31 type Tx struct { 32 originalTx []byte 33 tx *commandspb.Transaction 34 inputData *commandspb.InputData 35 pow *commandspb.ProofOfWork 36 version commandspb.TxVersion 37 } 38 39 func DecodeTxNoValidation(payload []byte) (*Tx, error) { 40 tx := &commandspb.Transaction{} 41 if err := proto.Unmarshal(payload, tx); err != nil { 42 return nil, fmt.Errorf("unable to unmarshal transaction: %w", err) 43 } 44 45 inputData, err := commands.CheckInputData(tx.InputData) 46 if err := err.ErrorOrNil(); err != nil { 47 return nil, err 48 } 49 50 return &Tx{ 51 originalTx: payload, 52 tx: tx, 53 inputData: inputData, 54 pow: tx.Pow, 55 version: tx.Version, 56 }, nil 57 } 58 59 func DecodeTx(payload []byte, chainID string) (*Tx, error) { 60 tx := &commandspb.Transaction{} 61 if err := proto.Unmarshal(payload, tx); err != nil { 62 return nil, fmt.Errorf("unable to unmarshal transaction: %w", err) 63 } 64 65 inputData, err := commands.CheckTransaction(tx, chainID) 66 if err != nil { 67 return nil, err 68 } 69 70 return &Tx{ 71 originalTx: payload, 72 tx: tx, 73 inputData: inputData, 74 pow: tx.Pow, 75 version: tx.Version, 76 }, nil 77 } 78 79 func (t Tx) Command() txn.Command { 80 switch cmd := t.inputData.Command.(type) { 81 case *commandspb.InputData_DelayedTransactionsWrapper: 82 return txn.DelayedTransactionsWrapper 83 case *commandspb.InputData_OrderSubmission: 84 return txn.SubmitOrderCommand 85 case *commandspb.InputData_OrderCancellation: 86 return txn.CancelOrderCommand 87 case *commandspb.InputData_OrderAmendment: 88 return txn.AmendOrderCommand 89 case *commandspb.InputData_VoteSubmission: 90 return txn.VoteCommand 91 case *commandspb.InputData_WithdrawSubmission: 92 return txn.WithdrawCommand 93 case *commandspb.InputData_LiquidityProvisionSubmission: 94 return txn.LiquidityProvisionCommand 95 case *commandspb.InputData_LiquidityProvisionCancellation: 96 return txn.CancelLiquidityProvisionCommand 97 case *commandspb.InputData_LiquidityProvisionAmendment: 98 return txn.AmendLiquidityProvisionCommand 99 case *commandspb.InputData_ProposalSubmission: 100 return txn.ProposeCommand 101 case *commandspb.InputData_AnnounceNode: 102 return txn.AnnounceNodeCommand 103 case *commandspb.InputData_NodeVote: 104 return txn.NodeVoteCommand 105 case *commandspb.InputData_NodeSignature: 106 return txn.NodeSignatureCommand 107 case *commandspb.InputData_ChainEvent: 108 return txn.ChainEventCommand 109 case *commandspb.InputData_OracleDataSubmission: 110 return txn.SubmitOracleDataCommand 111 case *commandspb.InputData_DelegateSubmission: 112 return txn.DelegateCommand 113 case *commandspb.InputData_UndelegateSubmission: 114 return txn.UndelegateCommand 115 case *commandspb.InputData_KeyRotateSubmission: 116 return txn.RotateKeySubmissionCommand 117 case *commandspb.InputData_StateVariableProposal: 118 return txn.StateVariableProposalCommand 119 case *commandspb.InputData_Transfer: 120 return txn.TransferFundsCommand 121 case *commandspb.InputData_CancelTransfer: 122 return txn.CancelTransferFundsCommand 123 case *commandspb.InputData_ValidatorHeartbeat: 124 return txn.ValidatorHeartbeatCommand 125 case *commandspb.InputData_EthereumKeyRotateSubmission: 126 return txn.RotateEthereumKeySubmissionCommand 127 case *commandspb.InputData_ProtocolUpgradeProposal: 128 return txn.ProtocolUpgradeCommand 129 case *commandspb.InputData_IssueSignatures: 130 return txn.IssueSignatures 131 case *commandspb.InputData_BatchMarketInstructions: 132 return txn.BatchMarketInstructions 133 case *commandspb.InputData_StopOrdersSubmission: 134 return txn.StopOrdersSubmissionCommand 135 case *commandspb.InputData_StopOrdersCancellation: 136 return txn.StopOrdersCancellationCommand 137 case *commandspb.InputData_CreateReferralSet: 138 return txn.CreateReferralSetCommand 139 case *commandspb.InputData_UpdateReferralSet: 140 return txn.UpdateReferralSetCommand 141 case *commandspb.InputData_ApplyReferralCode: 142 return txn.ApplyReferralCodeCommand 143 case *commandspb.InputData_UpdateMarginMode: 144 return txn.UpdateMarginModeCommand 145 case *commandspb.InputData_JoinTeam: 146 return txn.JoinTeamCommand 147 case *commandspb.InputData_BatchProposalSubmission: 148 return txn.BatchProposeCommand 149 case *commandspb.InputData_UpdatePartyProfile: 150 return txn.UpdatePartyProfileCommand 151 case *commandspb.InputData_SubmitAmm: 152 return txn.SubmitAMMCommand 153 case *commandspb.InputData_AmendAmm: 154 return txn.AmendAMMCommand 155 case *commandspb.InputData_CancelAmm: 156 return txn.CancelAMMCommand 157 default: 158 panic(fmt.Sprintf("command %T is not supported", cmd)) 159 } 160 } 161 162 func (t Tx) GetLength() int { 163 return len(t.originalTx) 164 } 165 166 func (t Tx) GetNonce() uint64 { 167 return t.inputData.Nonce 168 } 169 170 func (t Tx) GetPoWNonce() uint64 { 171 // The proof-of-work is not required by validator commands. So, it can be 172 // nil. 173 if t.pow == nil { 174 return 0 175 } 176 return t.pow.Nonce 177 } 178 179 func (t Tx) GetPoWTID() string { 180 // The proof-of-work is not required by validator commands. So, it can be 181 // nil. 182 if t.pow == nil { 183 return "" 184 } 185 return t.pow.Tid 186 } 187 188 func (t Tx) GetVersion() uint32 { return uint32(t.version) } 189 190 func (t Tx) GetCmd() interface{} { 191 switch cmd := t.inputData.Command.(type) { 192 case *commandspb.InputData_OrderSubmission: 193 return cmd.OrderSubmission 194 case *commandspb.InputData_OrderCancellation: 195 return cmd.OrderCancellation 196 case *commandspb.InputData_OrderAmendment: 197 return cmd.OrderAmendment 198 case *commandspb.InputData_VoteSubmission: 199 return cmd.VoteSubmission 200 case *commandspb.InputData_WithdrawSubmission: 201 return cmd.WithdrawSubmission 202 case *commandspb.InputData_LiquidityProvisionSubmission: 203 return cmd.LiquidityProvisionSubmission 204 case *commandspb.InputData_LiquidityProvisionCancellation: 205 return cmd.LiquidityProvisionCancellation 206 case *commandspb.InputData_LiquidityProvisionAmendment: 207 return cmd.LiquidityProvisionAmendment 208 case *commandspb.InputData_ProposalSubmission: 209 return cmd.ProposalSubmission 210 case *commandspb.InputData_AnnounceNode: 211 return cmd.AnnounceNode 212 case *commandspb.InputData_NodeVote: 213 return cmd.NodeVote 214 case *commandspb.InputData_NodeSignature: 215 return cmd.NodeSignature 216 case *commandspb.InputData_ChainEvent: 217 return cmd.ChainEvent 218 case *commandspb.InputData_OracleDataSubmission: 219 return cmd.OracleDataSubmission 220 case *commandspb.InputData_DelegateSubmission: 221 return cmd.DelegateSubmission 222 case *commandspb.InputData_UndelegateSubmission: 223 return cmd.UndelegateSubmission 224 case *commandspb.InputData_KeyRotateSubmission: 225 return cmd.KeyRotateSubmission 226 case *commandspb.InputData_StateVariableProposal: 227 return cmd.StateVariableProposal 228 case *commandspb.InputData_Transfer: 229 return cmd.Transfer 230 case *commandspb.InputData_CancelTransfer: 231 return cmd.CancelTransfer 232 case *commandspb.InputData_ValidatorHeartbeat: 233 return cmd.ValidatorHeartbeat 234 case *commandspb.InputData_EthereumKeyRotateSubmission: 235 return cmd.EthereumKeyRotateSubmission 236 case *commandspb.InputData_ProtocolUpgradeProposal: 237 return cmd.ProtocolUpgradeProposal 238 case *commandspb.InputData_IssueSignatures: 239 return cmd.IssueSignatures 240 case *commandspb.InputData_BatchMarketInstructions: 241 return cmd.BatchMarketInstructions 242 case *commandspb.InputData_StopOrdersSubmission: 243 return cmd.StopOrdersSubmission 244 case *commandspb.InputData_StopOrdersCancellation: 245 return cmd.StopOrdersCancellation 246 case *commandspb.InputData_CreateReferralSet: 247 return cmd.CreateReferralSet 248 case *commandspb.InputData_UpdateReferralSet: 249 return cmd.UpdateReferralSet 250 case *commandspb.InputData_ApplyReferralCode: 251 return cmd.ApplyReferralCode 252 case *commandspb.InputData_UpdateMarginMode: 253 return cmd.UpdateMarginMode 254 case *commandspb.InputData_JoinTeam: 255 return cmd.JoinTeam 256 case *commandspb.InputData_BatchProposalSubmission: 257 return cmd.BatchProposalSubmission 258 case *commandspb.InputData_UpdatePartyProfile: 259 return cmd.UpdatePartyProfile 260 case *commandspb.InputData_SubmitAmm: 261 return cmd.SubmitAmm 262 case *commandspb.InputData_AmendAmm: 263 return cmd.AmendAmm 264 case *commandspb.InputData_CancelAmm: 265 return cmd.CancelAmm 266 case *commandspb.InputData_DelayedTransactionsWrapper: 267 return cmd.DelayedTransactionsWrapper 268 default: 269 return fmt.Errorf("command %T is not supported", cmd) 270 } 271 } 272 273 func (t Tx) Unmarshal(i interface{}) error { 274 switch cmd := t.inputData.Command.(type) { 275 case *commandspb.InputData_ProtocolUpgradeProposal: 276 underlyingCmd, ok := i.(*commandspb.ProtocolUpgradeProposal) 277 if !ok { 278 return errors.New("failed to unmarshall to ProtocolUpgradeProposal") 279 } 280 *underlyingCmd = *cmd.ProtocolUpgradeProposal 281 case *commandspb.InputData_OrderSubmission: 282 underlyingCmd, ok := i.(*commandspb.OrderSubmission) 283 if !ok { 284 return errors.New("failed to unmarshall to OrderSubmission") 285 } 286 *underlyingCmd = *cmd.OrderSubmission 287 case *commandspb.InputData_OrderCancellation: 288 underlyingCmd, ok := i.(*commandspb.OrderCancellation) 289 if !ok { 290 return errors.New("failed to unmarshall to OrderCancellation") 291 } 292 *underlyingCmd = *cmd.OrderCancellation 293 case *commandspb.InputData_OrderAmendment: 294 underlyingCmd, ok := i.(*commandspb.OrderAmendment) 295 if !ok { 296 return errors.New("failed to unmarshall to OrderAmendment") 297 } 298 *underlyingCmd = *cmd.OrderAmendment 299 case *commandspb.InputData_VoteSubmission: 300 underlyingCmd, ok := i.(*commandspb.VoteSubmission) 301 if !ok { 302 return errors.New("failed to unmarshall to VoteSubmission") 303 } 304 *underlyingCmd = *cmd.VoteSubmission 305 case *commandspb.InputData_WithdrawSubmission: 306 underlyingCmd, ok := i.(*commandspb.WithdrawSubmission) 307 if !ok { 308 return errors.New("failed to unmarshall to WithdrawSubmission") 309 } 310 *underlyingCmd = *cmd.WithdrawSubmission 311 case *commandspb.InputData_LiquidityProvisionSubmission: 312 underlyingCmd, ok := i.(*commandspb.LiquidityProvisionSubmission) 313 if !ok { 314 return errors.New("failed to unmarshall to LiquidityProvisionSubmission") 315 } 316 *underlyingCmd = *cmd.LiquidityProvisionSubmission 317 case *commandspb.InputData_LiquidityProvisionCancellation: 318 underlyingCmd, ok := i.(*commandspb.LiquidityProvisionCancellation) 319 if !ok { 320 return errors.New("failed to unmarshall to LiquidityProvisionCancellation") 321 } 322 *underlyingCmd = *cmd.LiquidityProvisionCancellation 323 case *commandspb.InputData_LiquidityProvisionAmendment: 324 underlyingCmd, ok := i.(*commandspb.LiquidityProvisionAmendment) 325 if !ok { 326 return errors.New("failed to unmarshall to LiquidityProvisionAmendment") 327 } 328 *underlyingCmd = *cmd.LiquidityProvisionAmendment 329 case *commandspb.InputData_ProposalSubmission: 330 underlyingCmd, ok := i.(*commandspb.ProposalSubmission) 331 if !ok { 332 return errors.New("failed to unmarshall to ProposalSubmission") 333 } 334 *underlyingCmd = *cmd.ProposalSubmission 335 case *commandspb.InputData_AnnounceNode: 336 underlyingCmd, ok := i.(*commandspb.AnnounceNode) 337 if !ok { 338 return errors.New("failed to unmarshall to AnnounceNode") 339 } 340 *underlyingCmd = *cmd.AnnounceNode 341 case *commandspb.InputData_NodeVote: 342 underlyingCmd, ok := i.(*commandspb.NodeVote) 343 if !ok { 344 return errors.New("failed to unmarshall to NodeVote") 345 } 346 *underlyingCmd = *cmd.NodeVote 347 case *commandspb.InputData_NodeSignature: 348 underlyingCmd, ok := i.(*commandspb.NodeSignature) 349 if !ok { 350 return errors.New("failed to unmarshall to NodeSignature") 351 } 352 *underlyingCmd = *cmd.NodeSignature 353 case *commandspb.InputData_ChainEvent: 354 underlyingCmd, ok := i.(*commandspb.ChainEvent) 355 if !ok { 356 return errors.New("failed to unmarshall to ChainEvent") 357 } 358 *underlyingCmd = *cmd.ChainEvent 359 case *commandspb.InputData_OracleDataSubmission: 360 underlyingCmd, ok := i.(*commandspb.OracleDataSubmission) 361 if !ok { 362 return errors.New("failed to unmarshall to OracleDataSubmission") 363 } 364 *underlyingCmd = *cmd.OracleDataSubmission 365 case *commandspb.InputData_DelegateSubmission: 366 underlyingCmd, ok := i.(*commandspb.DelegateSubmission) 367 if !ok { 368 return errors.New("failed to unmarshall to DelegateSubmission") 369 } 370 *underlyingCmd = *cmd.DelegateSubmission 371 case *commandspb.InputData_UndelegateSubmission: 372 underlyingCmd, ok := i.(*commandspb.UndelegateSubmission) 373 if !ok { 374 return errors.New("failed to unmarshall to UndelegateSubmission") 375 } 376 *underlyingCmd = *cmd.UndelegateSubmission 377 case *commandspb.InputData_KeyRotateSubmission: 378 underlyingCmd, ok := i.(*commandspb.KeyRotateSubmission) 379 if !ok { 380 return errors.New("failed to unmarshal KeyRotateSubmission") 381 } 382 *underlyingCmd = *cmd.KeyRotateSubmission 383 case *commandspb.InputData_StateVariableProposal: 384 underlyingCmd, ok := i.(*commandspb.StateVariableProposal) 385 if !ok { 386 return errors.New("failed to unmarshal StateVariableProposal") 387 } 388 *underlyingCmd = *cmd.StateVariableProposal 389 case *commandspb.InputData_Transfer: 390 underlyingCmd, ok := i.(*commandspb.Transfer) 391 if !ok { 392 return errors.New("failed to unmarshal Transfer") 393 } 394 *underlyingCmd = *cmd.Transfer 395 case *commandspb.InputData_CancelTransfer: 396 underlyingCmd, ok := i.(*commandspb.CancelTransfer) 397 if !ok { 398 return errors.New("failed to unmarshal CancelTransferFunds") 399 } 400 *underlyingCmd = *cmd.CancelTransfer 401 case *commandspb.InputData_ValidatorHeartbeat: 402 underlyingCmd, ok := i.(*commandspb.ValidatorHeartbeat) 403 if !ok { 404 return errors.New("failed to unmarshal ValidatorHeartbeat") 405 } 406 *underlyingCmd = *cmd.ValidatorHeartbeat 407 case *commandspb.InputData_EthereumKeyRotateSubmission: 408 underlyingCmd, ok := i.(*commandspb.EthereumKeyRotateSubmission) 409 if !ok { 410 return errors.New("failed to unmarshal EthereumKeyRotateSubmission") 411 } 412 *underlyingCmd = *cmd.EthereumKeyRotateSubmission 413 case *commandspb.InputData_IssueSignatures: 414 underlyingCmd, ok := i.(*commandspb.IssueSignatures) 415 if !ok { 416 return errors.New("failed to unmarshall to IssueSignatures") 417 } 418 *underlyingCmd = *cmd.IssueSignatures 419 case *commandspb.InputData_BatchMarketInstructions: 420 underlyingCmd, ok := i.(*commandspb.BatchMarketInstructions) 421 if !ok { 422 return errors.New("failed to unmarshall to BatchMarketInstructions") 423 } 424 *underlyingCmd = *cmd.BatchMarketInstructions 425 case *commandspb.InputData_StopOrdersSubmission: 426 underlyingCmd, ok := i.(*commandspb.StopOrdersSubmission) 427 if !ok { 428 return errors.New("failed to unmarshall to StopOrdersSubmission") 429 } 430 *underlyingCmd = *cmd.StopOrdersSubmission 431 case *commandspb.InputData_StopOrdersCancellation: 432 underlyingCmd, ok := i.(*commandspb.StopOrdersCancellation) 433 if !ok { 434 return errors.New("failed to unmarshall to StopOrdersCancellation") 435 } 436 *underlyingCmd = *cmd.StopOrdersCancellation 437 case *commandspb.InputData_CreateReferralSet: 438 underlyingCmd, ok := i.(*commandspb.CreateReferralSet) 439 if !ok { 440 return errors.New("failed to unmarshall to CreateTeam") 441 } 442 *underlyingCmd = *cmd.CreateReferralSet 443 case *commandspb.InputData_UpdateReferralSet: 444 underlyingCmd, ok := i.(*commandspb.UpdateReferralSet) 445 if !ok { 446 return errors.New("failed to unmarshall to UpdateTeam") 447 } 448 *underlyingCmd = *cmd.UpdateReferralSet 449 case *commandspb.InputData_ApplyReferralCode: 450 underlyingCmd, ok := i.(*commandspb.ApplyReferralCode) 451 if !ok { 452 return errors.New("failed to unmarshall to ApplyReferralCode") 453 } 454 *underlyingCmd = *cmd.ApplyReferralCode 455 case *commandspb.InputData_JoinTeam: 456 underlyingCmd, ok := i.(*commandspb.JoinTeam) 457 if !ok { 458 return errors.New("failed to unmarshall to JoinTeam") 459 } 460 *underlyingCmd = *cmd.JoinTeam 461 case *commandspb.InputData_UpdateMarginMode: 462 underlyingCmd, ok := i.(*commandspb.UpdateMarginMode) 463 if !ok { 464 return errors.New("failed to unmarshall to UpdateMarginMode") 465 } 466 *underlyingCmd = *cmd.UpdateMarginMode 467 case *commandspb.InputData_BatchProposalSubmission: 468 underlyingCmd, ok := i.(*commandspb.BatchProposalSubmission) 469 if !ok { 470 return errors.New("failed to unmarshall to BatchProposalSubmission") 471 } 472 *underlyingCmd = *cmd.BatchProposalSubmission 473 case *commandspb.InputData_UpdatePartyProfile: 474 underlyingCmd, ok := i.(*commandspb.UpdatePartyProfile) 475 if !ok { 476 return errors.New("failed to unmarshall to UpdatePartyProfile") 477 } 478 *underlyingCmd = *cmd.UpdatePartyProfile 479 case *commandspb.InputData_SubmitAmm: 480 underlyingCmd, ok := i.(*commandspb.SubmitAMM) 481 if !ok { 482 return errors.New("failed to unmarshall to SubmitAMM") 483 } 484 *underlyingCmd = *cmd.SubmitAmm 485 case *commandspb.InputData_AmendAmm: 486 underlyingCmd, ok := i.(*commandspb.AmendAMM) 487 if !ok { 488 return errors.New("failed to unmarshall to AmendAMM") 489 } 490 *underlyingCmd = *cmd.AmendAmm 491 case *commandspb.InputData_CancelAmm: 492 underlyingCmd, ok := i.(*commandspb.CancelAMM) 493 if !ok { 494 return errors.New("failed to unmarshall to CancelAMM") 495 } 496 *underlyingCmd = *cmd.CancelAmm 497 case *commandspb.InputData_DelayedTransactionsWrapper: 498 underlyingCmd, ok := i.(*commandspb.DelayedTransactionsWrapper) 499 if !ok { 500 return errors.New("failed to unmarshall to DelayedTransactionsWrapper") 501 } 502 *underlyingCmd = *cmd.DelayedTransactionsWrapper 503 default: 504 return fmt.Errorf("command %T is not supported", cmd) 505 } 506 507 return nil 508 } 509 510 func (t Tx) PubKey() []byte { 511 decodedPubKey, err := hex.DecodeString(t.tx.GetPubKey()) 512 if err != nil { 513 panic("pub key should be hex encoded") 514 } 515 return decodedPubKey 516 } 517 518 func (t Tx) PubKeyHex() string { 519 return t.tx.GetPubKey() 520 } 521 522 func (t Tx) Party() string { 523 return t.tx.GetPubKey() 524 } 525 526 func (t Tx) Hash() []byte { 527 return tmhash.Sum(t.originalTx) 528 } 529 530 func (t Tx) Signature() []byte { 531 decodedSig, err := hex.DecodeString(t.tx.Signature.Value) 532 if err != nil { 533 panic("signature should be hex encoded") 534 } 535 return decodedSig 536 } 537 538 func (t Tx) BlockHeight() uint64 { 539 return t.inputData.BlockHeight 540 }