-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathbitcoin_like-transaction_outputs.ads
149 lines (130 loc) · 5.56 KB
/
bitcoin_like-transaction_outputs.ads
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
136
137
138
139
140
141
142
143
144
145
146
147
148
149
-- Copyright (C) 2019-2020 Dmitry Petukhov https://github.com/dgpv
--
-- This file is part of spark-bitcoin-transaction-example
--
-- It is subject to the license terms in the LICENSE file found in the top-level
-- directory of this distribution.
--
-- No part of spark-bitcoin-transaction-example, including this file, may be copied, modified,
-- propagated, or distributed except according to the terms contained in the
-- LICENSE file.
pragma SPARK_Mode(On);
with Data_Controls;
with Utils; use Utils;
with Bitcoin;
with Bitcoin_Like.Scripts;
with Bitcoin_Like.Data_Accessors;
with Bitcoin_Like.Transaction_Model;
with Bitcoin_Like.Utils;
use Bitcoin_Like.Utils;
generic
with package Data_Readers is new Bitcoin_Like.Data_Accessors.Readers (<>);
with package Data_Writers is new Bitcoin_Like.Data_Accessors.Writers (<>);
with package Scripts is new Bitcoin_Like.Scripts (Data_Readers => Data_Readers,
Data_Writers => Data_Writers,
others => <>);
type Satoshi_Type is range <>;
package Bitcoin_Like.Transaction_Outputs is
use Bitcoin_Like.Transaction_Model;
use Transaction_Model_Types;
use Data_Readers.Status_Control;
Output_Data_Model: constant Model_Type (Output_Tag_Type'Range) := (
Tag_Output_Value => Exact_Length(8),
Tag_Pubkey_Script => (
From => Long_Natural(Size_of_Compact_Size(1)),
To => Long_Natural(Size_of_Compact_Size(Scripts.Max_Data_Size) + Scripts.Max_Data_Size)
)
);
-- Output_Model_Max_Serialized_Data_Size: constant Positive := 8 + 1 + 83;
Output_Model_Max_Serialized_Data_Size: constant Positive := (
8 + Size_of_Compact_Size(Scripts.Max_Data_Size) + Scripts.Max_Data_Size
);
type Output_Type is
record
Value: Satoshi_Type;
Pubkey_Script: Scripts.Script_Type;
end record;
function Empty_Output return Output_Type is (
(
Value => 0,
Pubkey_Script => Scripts.Empty_Script
)
);
package Data_Checkpoints is new Data_Controls.Data_Checkpoints (
Status_Control => Data_Readers.Status_Control,
Model => Output_Data_Model
);
function Output_Serialized_Data_Length(Output: Output_Type) return Long_Natural
is (
Long_Natural(
8
+ Size_of_Compact_Size(Scripts.Script_Length(Output.Pubkey_Script))
+ Scripts.Script_Length(Output.Pubkey_Script)
)
)
with
-- Ghost => True,
Post => Output_Serialized_Data_Length'Result <= Long_Natural(Output_Model_Max_Serialized_Data_Size);
function Output_Ghost_Tape_Match(Output: Output_Type; Offset: Natural) return Boolean
is (
Data_Readers.Unsigned64_Ghost_Tape_Match(Unsigned_Modular_Int64(Output.Value), Offset)
and then
Scripts.Script_Ghost_Tape_Match(Output.Pubkey_Script, Offset + 8)
)
with Ghost => True,
Pre => Offset <= Natural'Last - Natural(Output_Serialized_Data_Length(Output)),
Global => (Input => Ghost_Data_Tape);
procedure Deserialize(Output: out Output_Type)
with
Pre => Status_OK,
Post => (
if Status_OK then (
-- Output.Value is fixed length, thus checked here
Data_Checkpoints.Final_State_Consistent(Bytes_Processed_Since(Raw_Data_Status'Old))
and then
Bytes_Processed_Since(Raw_Data_Status'Old) = Natural(Output_Serialized_Data_Length(Output))
and then
Data_Readers.Unsigned64_Ghost_Tape_Match(
Unsigned_Modular_Int64(Output.Value),
Data_Checkpoints.Checkpoint_States.Ghost_Tape_Position(
Tag_Output_Value, Data_Checkpoints.State))
and then
Data_Checkpoints.Element_Size_Match(
Tag_Pubkey_Script, Long_Natural(Scripts.Script_Serialized_Data_Length(Output.Pubkey_Script))
)
and then
Scripts.Script_Ghost_Tape_Match(
Output.Pubkey_Script,
Data_Checkpoints.Checkpoint_States.Ghost_Tape_Position(
Tag_Pubkey_Script, Data_Checkpoints.State))
and then
Output_Ghost_Tape_Match(Output, Bytes_Processed_With(Raw_Data_Status'Old))
and then
(
for all I in Ghost_Data_Tape'Range => (
if (
I < Bytes_Processed_With(Raw_Data_Status'Old)
or I >= Bytes_Processed_With(Raw_Data_Status'Old)
+ Natural(Output_Serialized_Data_Length(Output))
)
then Ghost_Data_Tape(I) = Ghost_Data_Tape'Old(I)
)
)
)
),
Depends => (
Output => (Raw_Data_Status, Structural_Status),
Data_Checkpoints.State =>+ (Raw_Data_Status, Structural_Status),
Data_Tag_State =>+ (Raw_Data_Status, Structural_Status),
Raw_Data_Status =>+ Structural_Status,
Structural_Status =>+ Raw_Data_Status,
Ghost_Data_Tape =>+ (Raw_Data_Status, Structural_Status)
),
Global => (
In_Out => (
Raw_Data_Status, Structural_Status, Data_Tag_State,
Data_Checkpoints.State, Ghost_Data_Tape
)
);
-- XXX procedure Serialize ...
end Bitcoin_Like.Transaction_Outputs;