Skip to content
/ fq Public
forked from wader/fq

Commit 5e7c01a

Browse files
committed
opentimestamps: address comments and improve things.
1 parent 0a22a32 commit 5e7c01a

File tree

8 files changed

+1750
-1734
lines changed

8 files changed

+1750
-1734
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,7 @@ mpeg_ts,
122122
[msgpack](doc/formats.md#msgpack),
123123
ogg,
124124
ogg_page,
125+
opentimestamps,
125126
opus_packet,
126127
[pcap](doc/formats.md#pcap),
127128
pcapng,

doc/formats.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@
9292
|[`msgpack`](#msgpack) |MessagePack |<sub></sub>|
9393
|`ogg` |OGG&nbsp;file |<sub>`ogg_page` `vorbis_packet` `opus_packet` `flac_metadatablock` `flac_frame`</sub>|
9494
|`ogg_page` |OGG&nbsp;page |<sub></sub>|
95+
|`opentimestamps` |OpenTimestamps&nbsp;file |<sub></sub>|
9596
|`opus_packet` |Opus&nbsp;packet |<sub>`vorbis_comment`</sub>|
9697
|[`pcap`](#pcap) |PCAP&nbsp;packet&nbsp;capture |<sub>`link_frame` `tcp_stream` `ipv4_packet`</sub>|
9798
|`pcapng` |PCAPNG&nbsp;packet&nbsp;capture |<sub>`link_frame` `tcp_stream` `ipv4_packet`</sub>|
@@ -130,7 +131,7 @@
130131
|`ip_packet` |Group |<sub>`icmp` `icmpv6` `tcp_segment` `udp_datagram`</sub>|
131132
|`link_frame` |Group |<sub>`bsd_loopback_frame` `ether8023_frame` `ipv4_packet` `ipv6_packet` `sll2_packet` `sll_packet`</sub>|
132133
|`mp3_frame_tags` |Group |<sub>`mp3_frame_vbri` `mp3_frame_xing`</sub>|
133-
|`probe` |Group |<sub>`adts` `aiff` `apple_bookmark` `ar` `avi` `avro_ocf` `bitcoin_blkdat` `bplist` `bzip2` `caff` `elf` `flac` `gif` `gzip` `html` `jpeg` `json` `jsonl` `luajit` `macho` `macho_fat` `matroska` `moc3` `mp3` `mp4` `mpeg_ts` `ogg` `pcap` `pcapng` `png` `tar` `tiff` `toml` `tzif` `wasm` `wav` `webp` `xml` `yaml` `zip`</sub>|
134+
|`probe` |Group |<sub>`adts` `aiff` `apple_bookmark` `ar` `avi` `avro_ocf` `bitcoin_blkdat` `bplist` `bzip2` `caff` `elf` `flac` `gif` `gzip` `html` `jpeg` `json` `jsonl` `luajit` `macho` `macho_fat` `matroska` `moc3` `mp3` `mp4` `mpeg_ts` `ogg` `opentimestamps` `pcap` `pcapng` `png` `tar` `tiff` `toml` `tzif` `wasm` `wav` `webp` `xml` `yaml` `zip`</sub>|
134135
|`tcp_stream` |Group |<sub>`dns_tcp` `rtmp` `tls`</sub>|
135136
|`udp_payload` |Group |<sub>`dns`</sub>|
136137

doc/formats.svg

Lines changed: 942 additions & 930 deletions
Loading

format/all/all.fqtest

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ $ fq -n _registry.groups.probe
2121
"moc3",
2222
"mp4",
2323
"ogg",
24+
"opentimestamps",
2425
"pcap",
2526
"pcapng",
2627
"png",
@@ -130,6 +131,7 @@ mpeg_ts MPEG Transport Stream
130131
msgpack MessagePack
131132
ogg OGG file
132133
ogg_page OGG page
134+
opentimestamps OpenTimestamps file
133135
opus_packet Opus packet
134136
pcap PCAP packet capture
135137
pcapng PCAPNG packet capture

format/format.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ var (
8383
Bitcoin_Block = &decode.Group{Name: "bitcoin_block"}
8484
Bitcoin_Script = &decode.Group{Name: "bitcoin_script"}
8585
Bitcoin_Transaction = &decode.Group{Name: "bitcoin_transaction"}
86-
OpenTimestamps = &decode.Group{Name: "ots"}
86+
Opentimestamps = &decode.Group{Name: "opentimestamps"}
8787
Bplist = &decode.Group{Name: "bplist"}
8888
BSD_Loopback_Frame = &decode.Group{Name: "bsd_loopback_frame"}
8989
BSON = &decode.Group{Name: "bson"}

format/opentimestamps/ots.go

Lines changed: 72 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -1,123 +1,123 @@
11
package opentimestamps
22

3-
import (
4-
"encoding/binary"
5-
"errors"
6-
"io"
3+
// https://opentimestamps.org/
74

5+
import (
86
"github.com/wader/fq/format"
97
"github.com/wader/fq/pkg/decode"
108
"github.com/wader/fq/pkg/interp"
119
"github.com/wader/fq/pkg/scalar"
10+
"golang.org/x/exp/slices"
1211
)
1312

1413
func init() {
1514
interp.RegisterFormat(
16-
format.OpenTimestamps,
15+
format.Opentimestamps,
1716
&decode.Format{
18-
Description: "OpenTimestamps file",
19-
Dependencies: nil,
20-
DecodeFn: decodeOTSFile,
17+
Description: "OpenTimestamps file",
18+
DecodeFn: decodeOTSFile,
19+
Groups: []*decode.Group{format.Probe},
2120
})
2221
}
2322

24-
func decodeVarInt(d *decode.D) uint64 {
25-
var value uint64 = 0
26-
var shift uint64 = 0
27-
28-
for {
29-
b := d.U8()
30-
value |= (b & 0b01111111) << shift
31-
shift += 7
32-
if b&0b10000000 == 0 {
33-
break
34-
}
35-
}
36-
37-
return value
38-
}
23+
const (
24+
continuationByte = 0xff
25+
attestationTag = 0x00
26+
appendTag = 0xf0
27+
prependTag = 0xf1
28+
reverseTag = 0xf2
29+
hexlifyTag = 0xf3
30+
sha1Tag = 0x02
31+
ripemd160Tag = 0x03
32+
sha256Tag = 0x08
33+
keccak256Tag = 0x67
34+
)
3935

4036
var (
41-
headerMagic = []byte{0x00, 0x4f, 0x70, 0x65, 0x6e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x73, 0x00, 0x00, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x00, 0xbf, 0x89, 0xe2, 0xe8, 0x84, 0xe8, 0x92, 0x94}
42-
pendingMagic = binary.BigEndian.Uint64([]byte{0x83, 0xdf, 0xe3, 0x0d, 0x2e, 0xf9, 0x0c, 0x8e})
43-
bitcoinMagic = binary.BigEndian.Uint64([]byte{0x05, 0x88, 0x96, 0x0d, 0x73, 0xd7, 0x19, 0x01})
37+
headerMagic = []byte{0x00, 0x4f, 0x70, 0x65, 0x6e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x73, 0x00, 0x00, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x00, 0xbf, 0x89, 0xe2, 0xe8, 0x84, 0xe8, 0x92, 0x94}
38+
calendarMagic uint64 = 0x83_df_e3_0d_2e_f9_0c_8e
39+
bitcoinMagic uint64 = 0x05_88_96_0d_73_d7_19_01
40+
41+
binaryTags = []byte{appendTag, prependTag}
4442
)
4543

4644
var attestationMapper = scalar.UintMapSymStr{
47-
pendingMagic: "calendar",
48-
bitcoinMagic: "bitcoin",
45+
calendarMagic: "calendar",
46+
bitcoinMagic: "bitcoin",
4947
}
5048

51-
var opMapper = scalar.UintMapSymStr{
52-
0xf0: "append",
53-
0xf1: "prepend",
54-
0xf2: "reverse",
55-
0xf3: "hexlify",
56-
0x02: "sha1",
57-
0x03: "ripemd160",
58-
0x08: "sha256",
59-
0x67: "keccak256",
60-
0x00: "attestation",
61-
0xff: "continuation_byte",
49+
var tagMapper = scalar.UintMapSymStr{
50+
continuationByte: "continuation_byte",
51+
attestationTag: "attestation",
52+
appendTag: "append",
53+
prependTag: "prepend",
54+
reverseTag: "reverse",
55+
hexlifyTag: "hexlify",
56+
sha1Tag: "sha1",
57+
ripemd160Tag: "ripemd160",
58+
sha256Tag: "sha256",
59+
keccak256Tag: "keccak256",
6260
}
6361

6462
func decodeOTSFile(d *decode.D) any {
6563
d.Endian = decode.BigEndian
6664

6765
d.FieldRawLen("magic_bytes", int64(8*len(headerMagic)), d.AssertBitBuf(headerMagic))
6866
d.FieldUintFn("version", decodeVarInt)
69-
tag := d.FieldU8("digest_hash_algorithm", opMapper,
70-
scalar.UintDescription("algorithm used to hash the source file"))
67+
tag := d.FieldU8("digest_hash_algorithm", tagMapper)
7168
if tag != 8 {
72-
name := opMapper[tag]
73-
d.Errorf("only sha256 supported, got %x: %s", tag, name)
69+
name := tagMapper[tag]
70+
d.Fatalf("only sha256 supported, got %x: %s", tag, name)
7471
return nil
7572
}
76-
d.FieldRawLen("digest", 8*32, scalar.RawHex,
77-
scalar.BitBufDescription("hash of the source file"))
73+
d.FieldRawLen("digest", 8*32, scalar.RawHex)
7874

79-
d.FieldArray("instructions", func(d *decode.D) {
80-
for {
81-
if b, err := d.TryPeekBytes(1); errors.Is(err, io.EOF) {
82-
break
83-
} else if b[0] == 0x00 {
84-
d.FieldStruct("attestation", func(d *decode.D) {
85-
d.FieldU8("attestation_tag", scalar.UintMapSymBool{0x00: true})
75+
d.FieldArray("operations", func(d *decode.D) {
76+
for d.NotEnd() {
77+
d.FieldStruct("operation", func(d *decode.D) {
78+
tag := d.FieldU8("tag", tagMapper)
79+
if tag == attestationTag {
8680
val := d.FieldU64BE("attestation_type", attestationMapper)
8781
d.FieldUintFn("attestation_varbytes_size", decodeVarInt)
8882
switch val {
8983
case bitcoinMagic:
90-
d.FieldUintFn("block", decodeVarInt,
91-
scalar.UintDescription("bitcoin block height to check for the merkle root"))
92-
case pendingMagic:
84+
d.FieldUintFn("block", decodeVarInt)
85+
case calendarMagic:
9386
nurl := d.FieldUintFn("url_size", decodeVarInt)
94-
d.FieldUTF8("url", int(nurl),
95-
scalar.StrDescription("url of the calendar server to get the final proof"))
87+
d.FieldUTF8("url", int(nurl))
9688
default:
97-
d.Errorf("unknown attestation tag %x", val)
89+
d.Fatalf("unknown attestation tag %x", val)
9890
}
99-
})
100-
} else if b[0] == 0xff {
101-
d.FieldStruct("continuation_byte", func(d *decode.D) {
102-
d.FieldU8("continuation_byte", scalar.UintMapSymBool{0xff: true},
103-
scalar.UintDescription("tells we should continue reading after the next attestation block"))
104-
})
105-
} else {
106-
d.FieldStruct("instruction", func(d *decode.D) {
107-
tag := d.FieldU8("op", opMapper)
108-
if name, ok := opMapper[tag]; ok {
91+
} else {
92+
if _, ok := tagMapper[tag]; ok {
10993
// read var bytes if argument
110-
if name == "append" || name == "prepend" {
94+
if slices.Contains(binaryTags, byte(tag)) {
11195
n := d.FieldUintFn("argument_size", decodeVarInt)
11296
d.FieldRawLen("argument", int64(8*n), scalar.RawHex)
11397
}
11498
} else {
115-
d.Errorf("unknown operation tag %x", tag)
99+
d.Fatalf("unknown operation tag %x", tag)
116100
}
117-
})
118-
}
101+
}
102+
})
119103
}
120104
})
121105

122106
return nil
123107
}
108+
109+
func decodeVarInt(d *decode.D) uint64 {
110+
var value uint64 = 0
111+
var shift uint64 = 0
112+
113+
for {
114+
b := d.U8()
115+
value |= (b & 0b01111111) << shift
116+
shift += 7
117+
if b&0b10000000 == 0 {
118+
break
119+
}
120+
}
121+
122+
return value
123+
}

0 commit comments

Comments
 (0)