summaryrefslogtreecommitdiff
path: root/ledger/ledgercore/error.go
blob: f5d347d6fbf39d142bacd2864ebaed2f09b45627 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
// Copyright (C) 2019-2023 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// go-algorand is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with go-algorand.  If not, see <https://www.gnu.org/licenses/>.

package ledgercore

import (
	"errors"
	"fmt"

	"github.com/algorand/go-algorand/data/basics"
	"github.com/algorand/go-algorand/data/transactions"
)

// ErrNoSpace indicates insufficient space for transaction in block
var ErrNoSpace = errors.New("block does not have space for transaction")

// TxnNotWellFormedError indicates a transaction was not well-formed when evaluated by the BlockEvaluator
//
//msgp:ignore TxnNotWellFormedError
type TxnNotWellFormedError string

func (err *TxnNotWellFormedError) Error() string {
	return string(*err)
}

// TransactionInLedgerError is returned when a transaction cannot be added because it has already been committed, either
// to the blockchain's ledger or to the history of changes tracked by a BlockEvaluator.
type TransactionInLedgerError struct {
	Txid             transactions.Txid
	InBlockEvaluator bool
}

// Error satisfies builtin interface `error`
func (tile TransactionInLedgerError) Error() string {
	return fmt.Sprintf("transaction already in ledger: %v", tile.Txid)
}

// LeaseInLedgerError is returned when a transaction cannot be added because it has a lease that already being used in the relevant rounds
type LeaseInLedgerError struct {
	txid             transactions.Txid
	lease            Txlease
	InBlockEvaluator bool
}

// MakeLeaseInLedgerError builds a LeaseInLedgerError object
func MakeLeaseInLedgerError(txid transactions.Txid, lease Txlease, inBlockEvaluator bool) *LeaseInLedgerError {
	return &LeaseInLedgerError{
		txid:             txid,
		lease:            lease,
		InBlockEvaluator: inBlockEvaluator,
	}
}

// Error implements the error interface for the LeaseInLedgerError stuct
func (lile *LeaseInLedgerError) Error() string {
	// format the lease as address.
	leaseValue := basics.Address(lile.lease.Lease)
	return fmt.Sprintf("transaction %v using an overlapping lease (sender, lease):(%s, %s)", lile.txid, lile.lease.Sender.String(), leaseValue.String())
}

// BlockInLedgerError is returned when a block cannot be added because it has already been done
type BlockInLedgerError struct {
	LastRound basics.Round
	NextRound basics.Round
}

// Error satisfies builtin interface `error`
func (bile BlockInLedgerError) Error() string {
	return fmt.Sprintf("block number already in ledger: block %d < next Round %d", bile.LastRound, bile.NextRound)
}

// ErrNoEntry is used to indicate that a block is not present in the ledger.
type ErrNoEntry struct {
	Round     basics.Round
	Latest    basics.Round
	Committed basics.Round
}

// Error satisfies builtin interface `error`
func (err ErrNoEntry) Error() string {
	return fmt.Sprintf("ledger does not have entry %d (latest %d, committed %d)", err.Round, err.Latest, err.Committed)
}

// ErrNonSequentialBlockEval provides feedback when the evaluator cannot be created for
// stale/future rounds.
type ErrNonSequentialBlockEval struct {
	EvaluatorRound basics.Round // EvaluatorRound is the round the evaluator was created for
	LatestRound    basics.Round // LatestRound is the latest round available on disk
}

// Error satisfies builtin interface `error`
func (err ErrNonSequentialBlockEval) Error() string {
	return fmt.Sprintf("block evaluation for round %d requires sequential evaluation while the latest round is %d", err.EvaluatorRound, err.LatestRound)
}

// TxGroupMalformedErrorReasonCode is a reason code for TxGroupMalformed
//
//msgp:ignore TxGroupMalformedErrorReasonCode
type TxGroupMalformedErrorReasonCode int

const (
	// TxGroupMalformedErrorReasonGeneric is a generic (not specific) reason code
	TxGroupMalformedErrorReasonGeneric TxGroupMalformedErrorReasonCode = iota
	// TxGroupMalformedErrorReasonExceedMaxSize indicates too large txgroup
	TxGroupMalformedErrorReasonExceedMaxSize
	// TxGroupMalformedErrorReasonInconsistentGroupID indicates different group IDs in a txgroup
	TxGroupMalformedErrorReasonInconsistentGroupID
	// TxGroupMalformedErrorReasonEmptyGroupID is for empty group ID but multiple transactions in a txgroup
	TxGroupMalformedErrorReasonEmptyGroupID
	// TxGroupMalformedErrorReasonIncompleteGroup indicates expected group ID does not match to provided
	TxGroupMalformedErrorReasonIncompleteGroup
)

// TxGroupMalformedError indicates txgroup has group ID problems or too large
type TxGroupMalformedError struct {
	Msg    string
	Reason TxGroupMalformedErrorReasonCode
}

func (e *TxGroupMalformedError) Error() string {
	return e.Msg
}