@@ -72,6 +72,23 @@ func (b *EthAPIBackend) HeaderByNumber(ctx context.Context, number rpc.BlockNumb
72
72
return b .eth .blockchain .GetHeaderByNumber (uint64 (number )), nil
73
73
}
74
74
75
+ func (b * EthAPIBackend ) HeaderByNumberOrHash (ctx context.Context , blockNrOrHash rpc.BlockNumberOrHash ) (* types.Header , error ) {
76
+ if blockNr , ok := blockNrOrHash .Number (); ok {
77
+ return b .HeaderByNumber (ctx , blockNr )
78
+ }
79
+ if hash , ok := blockNrOrHash .Hash (); ok {
80
+ header := b .eth .blockchain .GetHeaderByHash (hash )
81
+ if header == nil {
82
+ return nil , errors .New ("header for hash not found" )
83
+ }
84
+ if blockNrOrHash .RequireCanonical && b .eth .blockchain .GetCanonicalHash (header .Number .Uint64 ()) != hash {
85
+ return nil , errors .New ("hash is not currently canonical" )
86
+ }
87
+ return header , nil
88
+ }
89
+ return nil , errors .New ("invalid arguments; neither block nor hash specified" )
90
+ }
91
+
75
92
func (b * EthAPIBackend ) HeaderByHash (ctx context.Context , hash common.Hash ) (* types.Header , error ) {
76
93
return b .eth .blockchain .GetHeaderByHash (hash ), nil
77
94
}
@@ -93,6 +110,27 @@ func (b *EthAPIBackend) BlockByHash(ctx context.Context, hash common.Hash) (*typ
93
110
return b .eth .blockchain .GetBlockByHash (hash ), nil
94
111
}
95
112
113
+ func (b * EthAPIBackend ) BlockByNumberOrHash (ctx context.Context , blockNrOrHash rpc.BlockNumberOrHash ) (* types.Block , error ) {
114
+ if blockNr , ok := blockNrOrHash .Number (); ok {
115
+ return b .BlockByNumber (ctx , blockNr )
116
+ }
117
+ if hash , ok := blockNrOrHash .Hash (); ok {
118
+ header := b .eth .blockchain .GetHeaderByHash (hash )
119
+ if header == nil {
120
+ return nil , errors .New ("header for hash not found" )
121
+ }
122
+ if blockNrOrHash .RequireCanonical && b .eth .blockchain .GetCanonicalHash (header .Number .Uint64 ()) != hash {
123
+ return nil , errors .New ("hash is not currently canonical" )
124
+ }
125
+ block := b .eth .blockchain .GetBlock (hash , header .Number .Uint64 ())
126
+ if block == nil {
127
+ return nil , errors .New ("header found, but block body is missing" )
128
+ }
129
+ return block , nil
130
+ }
131
+ return nil , errors .New ("invalid arguments; neither block nor hash specified" )
132
+ }
133
+
96
134
func (b * EthAPIBackend ) StateAndHeaderByNumber (ctx context.Context , number rpc.BlockNumber ) (* state.StateDB , * types.Header , error ) {
97
135
// Pending state is only known by the miner
98
136
if number == rpc .PendingBlockNumber {
@@ -111,6 +149,27 @@ func (b *EthAPIBackend) StateAndHeaderByNumber(ctx context.Context, number rpc.B
111
149
return stateDb , header , err
112
150
}
113
151
152
+ func (b * EthAPIBackend ) StateAndHeaderByNumberOrHash (ctx context.Context , blockNrOrHash rpc.BlockNumberOrHash ) (* state.StateDB , * types.Header , error ) {
153
+ if blockNr , ok := blockNrOrHash .Number (); ok {
154
+ return b .StateAndHeaderByNumber (ctx , blockNr )
155
+ }
156
+ if hash , ok := blockNrOrHash .Hash (); ok {
157
+ header , err := b .HeaderByHash (ctx , hash )
158
+ if err != nil {
159
+ return nil , nil , err
160
+ }
161
+ if header == nil {
162
+ return nil , nil , errors .New ("header for hash not found" )
163
+ }
164
+ if blockNrOrHash .RequireCanonical && b .eth .blockchain .GetCanonicalHash (header .Number .Uint64 ()) != hash {
165
+ return nil , nil , errors .New ("hash is not currently canonical" )
166
+ }
167
+ stateDb , err := b .eth .BlockChain ().StateAt (header .Root )
168
+ return stateDb , header , err
169
+ }
170
+ return nil , nil , errors .New ("invalid arguments; neither block nor hash specified" )
171
+ }
172
+
114
173
func (b * EthAPIBackend ) GetReceipts (ctx context.Context , hash common.Hash ) (types.Receipts , error ) {
115
174
return b .eth .blockchain .GetReceiptsByHash (hash ), nil
116
175
}
0 commit comments