Fossil SCM

Merge recent trunk enhancements into the diff-js-refactoring branch.

drh 2021-09-11 00:30 diff-js-refactoring merge
Commit a7fbefee38a1c522920befb80386742b52facf3616b7531aca70aa91f67c73ae
+16 -6
--- src/branch.c
+++ src/branch.c
@@ -233,10 +233,11 @@
233233
** mtime Time of last checkin on this branch
234234
** isclosed True if the branch is closed
235235
** mergeto Another branch this branch was merged into
236236
** nckin Number of checkins on this branch
237237
** ckin Hash of the last checkin on this branch
238
+** isprivate True if the branch is private
238239
** bgclr Background color for this branch
239240
*/
240241
static const char createBrlistQuery[] =
241242
@ CREATE TEMP TABLE IF NOT EXISTS tmp_brlist AS
242243
@ SELECT
@@ -252,11 +253,12 @@
252253
@ AND tagxref.rid=plink.cid
253254
@ AND tagxref.tagid=(SELECT tagid FROM tag WHERE tagname='branch')
254255
@ AND tagtype>0) AS mergeto,
255256
@ count(*) AS nckin,
256257
@ (SELECT uuid FROM blob WHERE rid=tagxref.rid) AS ckin,
257
-@ event.bgcolor AS bgclr
258
+@ event.bgcolor AS bgclr,
259
+@ EXISTS(SELECT 1 FROM private WHERE rid=tagxref.rid) AS isprivate
258260
@ FROM tagxref, tag, event
259261
@ WHERE tagxref.tagid=tag.tagid
260262
@ AND tagxref.tagtype>0
261263
@ AND tag.tagname='branch'
262264
@ AND event.objid=tagxref.rid
@@ -277,10 +279,11 @@
277279
#define BRL_OPEN_ONLY 0x002 /* Show only open branches */
278280
#define BRL_BOTH 0x003 /* Show both open and closed branches */
279281
#define BRL_OPEN_CLOSED_MASK 0x003
280282
#define BRL_ORDERBY_MTIME 0x004 /* Sort by MTIME. (otherwise sort by name)*/
281283
#define BRL_REVERSE 0x008 /* Reverse the sort order */
284
+#define BRL_PRIVATE 0x010 /* Show only private branches */
282285
283286
#endif /* INTERFACE */
284287
285288
/*
286289
** Prepare a query that will list branches.
@@ -294,27 +297,28 @@
294297
blob_init(&sql, 0, 0);
295298
brlist_create_temp_table();
296299
switch( brFlags & BRL_OPEN_CLOSED_MASK ){
297300
case BRL_CLOSED_ONLY: {
298301
blob_append_sql(&sql,
299
- "SELECT name FROM tmp_brlist WHERE isclosed"
302
+ "SELECT name, isprivate FROM tmp_brlist WHERE isclosed"
300303
);
301304
break;
302305
}
303306
case BRL_BOTH: {
304307
blob_append_sql(&sql,
305
- "SELECT name FROM tmp_brlist WHERE 1"
308
+ "SELECT name, isprivate FROM tmp_brlist WHERE 1"
306309
);
307310
break;
308311
}
309312
case BRL_OPEN_ONLY: {
310313
blob_append_sql(&sql,
311
- "SELECT name FROM tmp_brlist WHERE NOT isclosed"
314
+ "SELECT name, isprivate FROM tmp_brlist WHERE NOT isclosed"
312315
);
313316
break;
314317
}
315318
}
319
+ if( brFlags & BRL_PRIVATE ) blob_append_sql(&sql, " AND isprivate");
316320
if(zBrNameGlob) blob_append_sql(&sql, " AND (name GLOB %Q)", zBrNameGlob);
317321
if( brFlags & BRL_ORDERBY_MTIME ){
318322
blob_append_sql(&sql, " ORDER BY -mtime");
319323
}else{
320324
blob_append_sql(&sql, " ORDER BY name COLLATE nocase");
@@ -585,14 +589,16 @@
585589
** > fossil branch list|ls ?OPTIONS? ?GLOB?
586590
**
587591
** List all branches. Options:
588592
** -a|--all List all branches. Default show only open branches
589593
** -c|--closed List closed branches.
594
+** -p List only private branches.
590595
** -r Reverse the sort order
591596
** -t Show recently changed branches first
592597
**
593
-** The current branch is marked with an asterisk.
598
+** The current branch is marked with an asterisk. Private branches are
599
+** marked with a hash sign.
594600
**
595601
** If GLOB is given, show only branches matching the pattern.
596602
**
597603
** > fossil branch new BRANCH-NAME BASIS ?OPTIONS?
598604
**
@@ -655,10 +661,11 @@
655661
int brFlags = BRL_OPEN_ONLY;
656662
if( find_option("all","a",0)!=0 ) brFlags = BRL_BOTH;
657663
if( find_option("closed","c",0)!=0 ) brFlags = BRL_CLOSED_ONLY;
658664
if( find_option("t",0,0)!=0 ) brFlags |= BRL_ORDERBY_MTIME;
659665
if( find_option("r",0,0)!=0 ) brFlags |= BRL_REVERSE;
666
+ if( find_option("p",0,0)!=0 ) brFlags |= BRL_PRIVATE;
660667
if( g.argc >= 4 ) zBrNameGlob = g.argv[3];
661668
662669
if( g.localOpen ){
663670
vid = db_lget_int("checkout", 0);
664671
zCurrent = db_text(0, "SELECT value FROM tagxref"
@@ -665,12 +672,15 @@
665672
" WHERE rid=%d AND tagid=%d", vid, TAG_BRANCH);
666673
}
667674
branch_prepare_list_query(&q, brFlags, zBrNameGlob);
668675
while( db_step(&q)==SQLITE_ROW ){
669676
const char *zBr = db_column_text(&q, 0);
677
+ int isPriv = zCurrent!=0 && db_column_int(&q, 1)==1;
670678
int isCur = zCurrent!=0 && fossil_strcmp(zCurrent,zBr)==0;
671
- fossil_print("%s%s\n", (isCur ? "* " : " "), zBr);
679
+ fossil_print("%s%s%s\n",
680
+ ( (brFlags & BRL_PRIVATE) ? " " : ( isPriv ? "#" : " ") ),
681
+ (isCur ? "* " : " "), zBr);
672682
}
673683
db_finalize(&q);
674684
}else if( strncmp(zCmd,"new",n)==0 ){
675685
branch_new();
676686
}else if( strncmp(zCmd,"close",5)==0 ){
677687
--- src/branch.c
+++ src/branch.c
@@ -233,10 +233,11 @@
233 ** mtime Time of last checkin on this branch
234 ** isclosed True if the branch is closed
235 ** mergeto Another branch this branch was merged into
236 ** nckin Number of checkins on this branch
237 ** ckin Hash of the last checkin on this branch
 
238 ** bgclr Background color for this branch
239 */
240 static const char createBrlistQuery[] =
241 @ CREATE TEMP TABLE IF NOT EXISTS tmp_brlist AS
242 @ SELECT
@@ -252,11 +253,12 @@
252 @ AND tagxref.rid=plink.cid
253 @ AND tagxref.tagid=(SELECT tagid FROM tag WHERE tagname='branch')
254 @ AND tagtype>0) AS mergeto,
255 @ count(*) AS nckin,
256 @ (SELECT uuid FROM blob WHERE rid=tagxref.rid) AS ckin,
257 @ event.bgcolor AS bgclr
 
258 @ FROM tagxref, tag, event
259 @ WHERE tagxref.tagid=tag.tagid
260 @ AND tagxref.tagtype>0
261 @ AND tag.tagname='branch'
262 @ AND event.objid=tagxref.rid
@@ -277,10 +279,11 @@
277 #define BRL_OPEN_ONLY 0x002 /* Show only open branches */
278 #define BRL_BOTH 0x003 /* Show both open and closed branches */
279 #define BRL_OPEN_CLOSED_MASK 0x003
280 #define BRL_ORDERBY_MTIME 0x004 /* Sort by MTIME. (otherwise sort by name)*/
281 #define BRL_REVERSE 0x008 /* Reverse the sort order */
 
282
283 #endif /* INTERFACE */
284
285 /*
286 ** Prepare a query that will list branches.
@@ -294,27 +297,28 @@
294 blob_init(&sql, 0, 0);
295 brlist_create_temp_table();
296 switch( brFlags & BRL_OPEN_CLOSED_MASK ){
297 case BRL_CLOSED_ONLY: {
298 blob_append_sql(&sql,
299 "SELECT name FROM tmp_brlist WHERE isclosed"
300 );
301 break;
302 }
303 case BRL_BOTH: {
304 blob_append_sql(&sql,
305 "SELECT name FROM tmp_brlist WHERE 1"
306 );
307 break;
308 }
309 case BRL_OPEN_ONLY: {
310 blob_append_sql(&sql,
311 "SELECT name FROM tmp_brlist WHERE NOT isclosed"
312 );
313 break;
314 }
315 }
 
316 if(zBrNameGlob) blob_append_sql(&sql, " AND (name GLOB %Q)", zBrNameGlob);
317 if( brFlags & BRL_ORDERBY_MTIME ){
318 blob_append_sql(&sql, " ORDER BY -mtime");
319 }else{
320 blob_append_sql(&sql, " ORDER BY name COLLATE nocase");
@@ -585,14 +589,16 @@
585 ** > fossil branch list|ls ?OPTIONS? ?GLOB?
586 **
587 ** List all branches. Options:
588 ** -a|--all List all branches. Default show only open branches
589 ** -c|--closed List closed branches.
 
590 ** -r Reverse the sort order
591 ** -t Show recently changed branches first
592 **
593 ** The current branch is marked with an asterisk.
 
594 **
595 ** If GLOB is given, show only branches matching the pattern.
596 **
597 ** > fossil branch new BRANCH-NAME BASIS ?OPTIONS?
598 **
@@ -655,10 +661,11 @@
655 int brFlags = BRL_OPEN_ONLY;
656 if( find_option("all","a",0)!=0 ) brFlags = BRL_BOTH;
657 if( find_option("closed","c",0)!=0 ) brFlags = BRL_CLOSED_ONLY;
658 if( find_option("t",0,0)!=0 ) brFlags |= BRL_ORDERBY_MTIME;
659 if( find_option("r",0,0)!=0 ) brFlags |= BRL_REVERSE;
 
660 if( g.argc >= 4 ) zBrNameGlob = g.argv[3];
661
662 if( g.localOpen ){
663 vid = db_lget_int("checkout", 0);
664 zCurrent = db_text(0, "SELECT value FROM tagxref"
@@ -665,12 +672,15 @@
665 " WHERE rid=%d AND tagid=%d", vid, TAG_BRANCH);
666 }
667 branch_prepare_list_query(&q, brFlags, zBrNameGlob);
668 while( db_step(&q)==SQLITE_ROW ){
669 const char *zBr = db_column_text(&q, 0);
 
670 int isCur = zCurrent!=0 && fossil_strcmp(zCurrent,zBr)==0;
671 fossil_print("%s%s\n", (isCur ? "* " : " "), zBr);
 
 
672 }
673 db_finalize(&q);
674 }else if( strncmp(zCmd,"new",n)==0 ){
675 branch_new();
676 }else if( strncmp(zCmd,"close",5)==0 ){
677
--- src/branch.c
+++ src/branch.c
@@ -233,10 +233,11 @@
233 ** mtime Time of last checkin on this branch
234 ** isclosed True if the branch is closed
235 ** mergeto Another branch this branch was merged into
236 ** nckin Number of checkins on this branch
237 ** ckin Hash of the last checkin on this branch
238 ** isprivate True if the branch is private
239 ** bgclr Background color for this branch
240 */
241 static const char createBrlistQuery[] =
242 @ CREATE TEMP TABLE IF NOT EXISTS tmp_brlist AS
243 @ SELECT
@@ -252,11 +253,12 @@
253 @ AND tagxref.rid=plink.cid
254 @ AND tagxref.tagid=(SELECT tagid FROM tag WHERE tagname='branch')
255 @ AND tagtype>0) AS mergeto,
256 @ count(*) AS nckin,
257 @ (SELECT uuid FROM blob WHERE rid=tagxref.rid) AS ckin,
258 @ event.bgcolor AS bgclr,
259 @ EXISTS(SELECT 1 FROM private WHERE rid=tagxref.rid) AS isprivate
260 @ FROM tagxref, tag, event
261 @ WHERE tagxref.tagid=tag.tagid
262 @ AND tagxref.tagtype>0
263 @ AND tag.tagname='branch'
264 @ AND event.objid=tagxref.rid
@@ -277,10 +279,11 @@
279 #define BRL_OPEN_ONLY 0x002 /* Show only open branches */
280 #define BRL_BOTH 0x003 /* Show both open and closed branches */
281 #define BRL_OPEN_CLOSED_MASK 0x003
282 #define BRL_ORDERBY_MTIME 0x004 /* Sort by MTIME. (otherwise sort by name)*/
283 #define BRL_REVERSE 0x008 /* Reverse the sort order */
284 #define BRL_PRIVATE 0x010 /* Show only private branches */
285
286 #endif /* INTERFACE */
287
288 /*
289 ** Prepare a query that will list branches.
@@ -294,27 +297,28 @@
297 blob_init(&sql, 0, 0);
298 brlist_create_temp_table();
299 switch( brFlags & BRL_OPEN_CLOSED_MASK ){
300 case BRL_CLOSED_ONLY: {
301 blob_append_sql(&sql,
302 "SELECT name, isprivate FROM tmp_brlist WHERE isclosed"
303 );
304 break;
305 }
306 case BRL_BOTH: {
307 blob_append_sql(&sql,
308 "SELECT name, isprivate FROM tmp_brlist WHERE 1"
309 );
310 break;
311 }
312 case BRL_OPEN_ONLY: {
313 blob_append_sql(&sql,
314 "SELECT name, isprivate FROM tmp_brlist WHERE NOT isclosed"
315 );
316 break;
317 }
318 }
319 if( brFlags & BRL_PRIVATE ) blob_append_sql(&sql, " AND isprivate");
320 if(zBrNameGlob) blob_append_sql(&sql, " AND (name GLOB %Q)", zBrNameGlob);
321 if( brFlags & BRL_ORDERBY_MTIME ){
322 blob_append_sql(&sql, " ORDER BY -mtime");
323 }else{
324 blob_append_sql(&sql, " ORDER BY name COLLATE nocase");
@@ -585,14 +589,16 @@
589 ** > fossil branch list|ls ?OPTIONS? ?GLOB?
590 **
591 ** List all branches. Options:
592 ** -a|--all List all branches. Default show only open branches
593 ** -c|--closed List closed branches.
594 ** -p List only private branches.
595 ** -r Reverse the sort order
596 ** -t Show recently changed branches first
597 **
598 ** The current branch is marked with an asterisk. Private branches are
599 ** marked with a hash sign.
600 **
601 ** If GLOB is given, show only branches matching the pattern.
602 **
603 ** > fossil branch new BRANCH-NAME BASIS ?OPTIONS?
604 **
@@ -655,10 +661,11 @@
661 int brFlags = BRL_OPEN_ONLY;
662 if( find_option("all","a",0)!=0 ) brFlags = BRL_BOTH;
663 if( find_option("closed","c",0)!=0 ) brFlags = BRL_CLOSED_ONLY;
664 if( find_option("t",0,0)!=0 ) brFlags |= BRL_ORDERBY_MTIME;
665 if( find_option("r",0,0)!=0 ) brFlags |= BRL_REVERSE;
666 if( find_option("p",0,0)!=0 ) brFlags |= BRL_PRIVATE;
667 if( g.argc >= 4 ) zBrNameGlob = g.argv[3];
668
669 if( g.localOpen ){
670 vid = db_lget_int("checkout", 0);
671 zCurrent = db_text(0, "SELECT value FROM tagxref"
@@ -665,12 +672,15 @@
672 " WHERE rid=%d AND tagid=%d", vid, TAG_BRANCH);
673 }
674 branch_prepare_list_query(&q, brFlags, zBrNameGlob);
675 while( db_step(&q)==SQLITE_ROW ){
676 const char *zBr = db_column_text(&q, 0);
677 int isPriv = zCurrent!=0 && db_column_int(&q, 1)==1;
678 int isCur = zCurrent!=0 && fossil_strcmp(zCurrent,zBr)==0;
679 fossil_print("%s%s%s\n",
680 ( (brFlags & BRL_PRIVATE) ? " " : ( isPriv ? "#" : " ") ),
681 (isCur ? "* " : " "), zBr);
682 }
683 db_finalize(&q);
684 }else if( strncmp(zCmd,"new",n)==0 ){
685 branch_new();
686 }else if( strncmp(zCmd,"close",5)==0 ){
687
+9 -1
--- src/diff.c
+++ src/diff.c
@@ -2092,11 +2092,19 @@
20922092
a += skip;
20932093
b += skip;
20942094
m = R[r] - skip;
20952095
if( r ) skip -= nContext;
20962096
if( skip>0 ){
2097
- pBuilder->xSkip(pBuilder, skip, 0);
2097
+ if( skip<nContext ){
2098
+ /* If the amount to skip is less that the context band, then
2099
+ ** go ahead and show the skip band as it is not worth eliding */
2100
+ for(j=0; j<skip; j++){
2101
+ pBuilder->xCommon(pBuilder, &A[a+j-skip]);
2102
+ }
2103
+ }else{
2104
+ pBuilder->xSkip(pBuilder, skip, 0);
2105
+ }
20982106
}
20992107
for(j=0; j<m; j++){
21002108
pBuilder->xCommon(pBuilder, &A[a+j]);
21012109
}
21022110
a += m;
21032111
--- src/diff.c
+++ src/diff.c
@@ -2092,11 +2092,19 @@
2092 a += skip;
2093 b += skip;
2094 m = R[r] - skip;
2095 if( r ) skip -= nContext;
2096 if( skip>0 ){
2097 pBuilder->xSkip(pBuilder, skip, 0);
 
 
 
 
 
 
 
 
2098 }
2099 for(j=0; j<m; j++){
2100 pBuilder->xCommon(pBuilder, &A[a+j]);
2101 }
2102 a += m;
2103
--- src/diff.c
+++ src/diff.c
@@ -2092,11 +2092,19 @@
2092 a += skip;
2093 b += skip;
2094 m = R[r] - skip;
2095 if( r ) skip -= nContext;
2096 if( skip>0 ){
2097 if( skip<nContext ){
2098 /* If the amount to skip is less that the context band, then
2099 ** go ahead and show the skip band as it is not worth eliding */
2100 for(j=0; j<skip; j++){
2101 pBuilder->xCommon(pBuilder, &A[a+j-skip]);
2102 }
2103 }else{
2104 pBuilder->xSkip(pBuilder, skip, 0);
2105 }
2106 }
2107 for(j=0; j<m; j++){
2108 pBuilder->xCommon(pBuilder, &A[a+j]);
2109 }
2110 a += m;
2111
+9 -1
--- src/diff.c
+++ src/diff.c
@@ -2092,11 +2092,19 @@
20922092
a += skip;
20932093
b += skip;
20942094
m = R[r] - skip;
20952095
if( r ) skip -= nContext;
20962096
if( skip>0 ){
2097
- pBuilder->xSkip(pBuilder, skip, 0);
2097
+ if( skip<nContext ){
2098
+ /* If the amount to skip is less that the context band, then
2099
+ ** go ahead and show the skip band as it is not worth eliding */
2100
+ for(j=0; j<skip; j++){
2101
+ pBuilder->xCommon(pBuilder, &A[a+j-skip]);
2102
+ }
2103
+ }else{
2104
+ pBuilder->xSkip(pBuilder, skip, 0);
2105
+ }
20982106
}
20992107
for(j=0; j<m; j++){
21002108
pBuilder->xCommon(pBuilder, &A[a+j]);
21012109
}
21022110
a += m;
21032111
--- src/diff.c
+++ src/diff.c
@@ -2092,11 +2092,19 @@
2092 a += skip;
2093 b += skip;
2094 m = R[r] - skip;
2095 if( r ) skip -= nContext;
2096 if( skip>0 ){
2097 pBuilder->xSkip(pBuilder, skip, 0);
 
 
 
 
 
 
 
 
2098 }
2099 for(j=0; j<m; j++){
2100 pBuilder->xCommon(pBuilder, &A[a+j]);
2101 }
2102 a += m;
2103
--- src/diff.c
+++ src/diff.c
@@ -2092,11 +2092,19 @@
2092 a += skip;
2093 b += skip;
2094 m = R[r] - skip;
2095 if( r ) skip -= nContext;
2096 if( skip>0 ){
2097 if( skip<nContext ){
2098 /* If the amount to skip is less that the context band, then
2099 ** go ahead and show the skip band as it is not worth eliding */
2100 for(j=0; j<skip; j++){
2101 pBuilder->xCommon(pBuilder, &A[a+j-skip]);
2102 }
2103 }else{
2104 pBuilder->xSkip(pBuilder, skip, 0);
2105 }
2106 }
2107 for(j=0; j<m; j++){
2108 pBuilder->xCommon(pBuilder, &A[a+j]);
2109 }
2110 a += m;
2111
+35 -34
--- www/blockchain.md
+++ www/blockchain.md
@@ -11,25 +11,24 @@
1111
1212
The [Wikipedia definition of "blockchain"][bcwp] begins:
1313
1414
>
1515
"A blockchain…is a growing list of records, called blocks, which are linked using
16
- cryptography. Each block contains a cryptographic hash of the previous
16
+ cryptography… Each block contains a cryptographic hash of the previous
1717
block, a timestamp, and transaction data (generally represented as a Merkle tree)."
1818
19
-
20
-By that partial definition, Fossil is indeed a blockchain. The blocks
19
+Point-for-point, Fossil follows this partial definition.
20
+The blocks
2121
are Fossil’s ["manifest" artifacts](./fileformat.wiki#manifest). Each
2222
manifest has a cryptographically-strong [SHA-1] or [SHA-3] hash linking it to
2323
one or more “parent” blocks. The manifest also contains a timestamp and
24
-the transactional data needed to express a commit to the repository. If
25
-you traverse the Fossil repository from the tips of its [DAG] to the
26
-root by following the parent hashes in each manifest, you will then have
27
-a Merkle tree. Point-for-point, Fossil follows that definition.
28
-
24
+the transactional data needed to express a commit to the repository.
25
+To traverse the Fossil repository from the tips of its [DAG] to the
26
+root by following the parent hashes in each manifest is to traverse
27
+a Merkle tree.
2928
Every change in Fossil starts by adding one or more manifests to
30
-the repository, extending this tree.
29
+the repository, extending this Merkle tree.
3130
3231
[bcwp]: https://en.wikipedia.org/wiki/Blockchain
3332
[DAG]: https://en.wikipedia.org/wiki/Directed_acyclic_graph
3433
[SHA-1]: https://en.wikipedia.org/wiki/SHA-1
3534
[SHA-3]: https://en.wikipedia.org/wiki/SHA-3
@@ -61,11 +60,12 @@
6160
* **Type 2** is creation of new fraudulent currency that will pass
6261
in commerce. To extend our analogy, it is the creation of new
6362
US $10 bills. There are two sub-types to this fraud. In terms of
6463
our analogy, they are:
6564
66
- * **Type 2a**: copying of an existing legitimate $10 bill
65
+ * **Type 2a**: copying an existing legitimate $10 bill<p>
66
+
6767
* **Type 2b**: printing a new $10 bill that is unlike an existing
6868
legitimate one, yet which will still pass in commerce
6969
7070
* **Type 3** is double-spending existing legitimate cryptocurrency.
7171
There is no analogy in paper money due to its physical form; it is a
@@ -92,11 +92,11 @@
9292
cryptocurrencies add a separate chain of hashes to make checking
9393
for double-spending quick and easy.
9494
9595
Fossil has [a disabled-by-default feature][cs] to call out to an
9696
external copy of [PGP] or [GPG] to sign commit manifests before
97
- inserting them into the repository. You may wish to couple that with
97
+ inserting them into the repository. You can couple that with
9898
a server-side [after-receive hook][arh] to reject unsigned commits.
9999
100100
Although there are several distinctions you can draw between the way
101101
Fossil’s commit signing scheme works and the way block signing works
102102
in cryptocurrencies, only one is of material interest for our
@@ -112,11 +112,11 @@
112112
prevention, both Type 1 and Type 2. You cannot modify existing
113113
commits (Type 1 forgery) because you do not have the original
114114
committer’s private signing key, and you cannot forge new commits
115115
attesting to come from some other trusted committer (Type 2) because
116116
you don’t have any of their private signing keys, either.
117
- Cyrptocurrencies also use the work problem to prevent Type 2
117
+ Cryptocurrencies use the work problem to prevent Type 2
118118
forgeries, but the application of that to Fossil is a matter we get
119119
to [later](#work).
120120
121121
Although you have complete control over the contents of your local
122122
Fossil repository clone, you cannot perform Type 1 forgery on its
@@ -124,24 +124,26 @@
124124
algorithm. ([SHA3-256][SHA-3] by default in the current version of
125125
Fossil.) Even if you could, Fossil’s sync protocol will prevent the
126126
modification from being pushed into another repository: the remote
127127
Fossil instance says, “I’ve already got that one, thanks,” and
128128
ignores the push. Thus, short of breaking into the remote server
129
- and modifying the repository in place, you couldn’t even make use of
130
- a preimage attack if you had that power. This is an attack on the
129
+ and modifying the repository in place, you couldn’t make use of
130
+ a preimage attack even if you had that power. Further, that would be an attack on the
131131
server itself, not on Fossil’s data structures, so while it is
132
- useful to think through this problem, it is not helpful to answering
132
+ useful to think through this problem, it is not helpful in answering
133133
our questions here.
134134
135
- The Fossil sync protocol also prevents the closest analog to Type 3
135
+ The Fossil sync protocol’s duplication detection also prevents the closest analog to Type 3
136136
frauds in Fossil: copying a commit manifest in your local repo clone
137137
won’t result in a double-commit on sync.
138138
139139
In the absence of digital signatures, Fossil’s [RBAC system][caps]
140140
restricts Type 2 forgery to trusted committers. Thus once again
141141
we’re reduced to an infosec problem, not a data structure design
142
- question. (Inversely, enabling commit clearsigning is a good idea
142
+ question.
143
+
144
+ (Inversely, enabling commit clearsigning is a good idea
143145
if you have committers on your repo whom you don’t trust not to
144146
commit Type 2 frauds. But let us be clear: your choice of setting
145147
does not answer the question of whether Fossil is a blockchain.)
146148
147149
If Fossil signatures prevent Type 1 and Type 2 frauds, you
@@ -245,19 +247,22 @@
245247
to change the value of existing commits (Type 1) or add new commits to
246248
the repository (Type 2).
247249
248250
What if we removed those features from Fossil, creating an append-only
249251
Fossil variant? Is it a DLT then? Arguably still not, because [today’s Fossil
250
-is an AP-mode system][ctap] in the [CAP theorem][cap] sense, which means
252
+is an AP-mode system][ctap], which means
251253
there can be no guaranteed consensus on the content of the ledger at any
252
-given time. If you had an AP-mode accounts receivable system, it could
253
-have different bottom-line totals at different sites, because you’ve
254
-cast away “C” to get AP-mode operation.
254
+given time. An AP-mode accounts receivable system would allow
255
+different bottom-line totals at different sites, because you’ve
256
+cast away “C” to get AP-mode operation. (See the prior link or
257
+[Wikipedia’s article on the CAP theorem][cap] if you aren’t following
258
+this terminology.)
255259
256
-Because of this, you could still not guarantee that the command
257
-“`fossil info tip`” gives the same result everywhere. A CA or CP-mode Fossil
258
-variant would guarantee that everyone got the same result. (Everyone not
260
+By the same token, you cannot guarantee that the command
261
+“`fossil info tip`” gives the same result everywhere. You would need to
262
+recast Fossil as a CA or CP-mode system to solve that.
263
+(Everyone not
259264
partitioned away from the majority of the network at any rate, in the CP
260265
case.)
261266
262267
What are the prospects for CA-mode or CP-mode Fossil? [We don’t want
263268
CA-mode Fossil][ctca], but [CP-mode could be useful][ctcp]. Until the latter
@@ -366,13 +371,13 @@
366371
commits into your repository under any name they want.
367372
368373
On the server side, you can also [scrub] the logging that remembers
369374
where each commit came from.
370375
371
-That info isn’t transmitted from the remote server on clone or pull.
372
-Instead, the size of the `rcvfrom` table after initial clone is 1: it
373
-contains the remote server’s IP address. On each pull containing new
376
+Commit source info isn’t transmitted from the remote server on clone or pull:
377
+the size of the `rcvfrom` table after initial clone is 1, containing
378
+only the remote server’s IP address. On each pull containing new
374379
artifacts, your local `fossil` instance adds another entry to this
375380
table, likely with the same IP address unless the server has moved or
376381
you’re using [multiple remotes][mrep]. This table is far more
377382
interesting on the server side, containing the IP addresses of all
378383
contentful pushes; thus [the `scrub` command][scrub].
@@ -452,18 +457,14 @@
452457
453458
# Conclusion
454459
455460
This author believes it is technologically indefensible to call Fossil a
456461
“blockchain” in any sense likely to be understood by a majority of those
457
-you’re communicating with.
458
-
459
-Within a certain narrow scope, you can defend this usage, but if you do
460
-that, you’ve failed any goal that requires clear communication: it
461
-doesn’t work to use a term in a nonstandard way just because you can
462
-defend it. The people you’re communicating your ideas to must have the
462
+you’re communicating with. Using a term in a nonstandard way just because you can
463
+defend it means you’ve failed any goal that requires clear communication.
464
+The people you’re communicating your ideas to must have the
463465
same concept of the terms you use.
464
-
465466
466467
What term should you use instead? Fossil stores a DAG of hash-chained
467468
commits, so an indisputably correct term is a [Merkle tree][mt], named
468469
after [its inventor][drrm]. You could also use the more generic term
469470
“hash tree.”
470471
--- www/blockchain.md
+++ www/blockchain.md
@@ -11,25 +11,24 @@
11
12 The [Wikipedia definition of "blockchain"][bcwp] begins:
13
14 >
15 "A blockchain…is a growing list of records, called blocks, which are linked using
16 cryptography. Each block contains a cryptographic hash of the previous
17 block, a timestamp, and transaction data (generally represented as a Merkle tree)."
18
19
20 By that partial definition, Fossil is indeed a blockchain. The blocks
21 are Fossil’s ["manifest" artifacts](./fileformat.wiki#manifest). Each
22 manifest has a cryptographically-strong [SHA-1] or [SHA-3] hash linking it to
23 one or more “parent” blocks. The manifest also contains a timestamp and
24 the transactional data needed to express a commit to the repository. If
25 you traverse the Fossil repository from the tips of its [DAG] to the
26 root by following the parent hashes in each manifest, you will then have
27 a Merkle tree. Point-for-point, Fossil follows that definition.
28
29 Every change in Fossil starts by adding one or more manifests to
30 the repository, extending this tree.
31
32 [bcwp]: https://en.wikipedia.org/wiki/Blockchain
33 [DAG]: https://en.wikipedia.org/wiki/Directed_acyclic_graph
34 [SHA-1]: https://en.wikipedia.org/wiki/SHA-1
35 [SHA-3]: https://en.wikipedia.org/wiki/SHA-3
@@ -61,11 +60,12 @@
61 * **Type 2** is creation of new fraudulent currency that will pass
62 in commerce. To extend our analogy, it is the creation of new
63 US $10 bills. There are two sub-types to this fraud. In terms of
64 our analogy, they are:
65
66 * **Type 2a**: copying of an existing legitimate $10 bill
 
67 * **Type 2b**: printing a new $10 bill that is unlike an existing
68 legitimate one, yet which will still pass in commerce
69
70 * **Type 3** is double-spending existing legitimate cryptocurrency.
71 There is no analogy in paper money due to its physical form; it is a
@@ -92,11 +92,11 @@
92 cryptocurrencies add a separate chain of hashes to make checking
93 for double-spending quick and easy.
94
95 Fossil has [a disabled-by-default feature][cs] to call out to an
96 external copy of [PGP] or [GPG] to sign commit manifests before
97 inserting them into the repository. You may wish to couple that with
98 a server-side [after-receive hook][arh] to reject unsigned commits.
99
100 Although there are several distinctions you can draw between the way
101 Fossil’s commit signing scheme works and the way block signing works
102 in cryptocurrencies, only one is of material interest for our
@@ -112,11 +112,11 @@
112 prevention, both Type 1 and Type 2. You cannot modify existing
113 commits (Type 1 forgery) because you do not have the original
114 committer’s private signing key, and you cannot forge new commits
115 attesting to come from some other trusted committer (Type 2) because
116 you don’t have any of their private signing keys, either.
117 Cyrptocurrencies also use the work problem to prevent Type 2
118 forgeries, but the application of that to Fossil is a matter we get
119 to [later](#work).
120
121 Although you have complete control over the contents of your local
122 Fossil repository clone, you cannot perform Type 1 forgery on its
@@ -124,24 +124,26 @@
124 algorithm. ([SHA3-256][SHA-3] by default in the current version of
125 Fossil.) Even if you could, Fossil’s sync protocol will prevent the
126 modification from being pushed into another repository: the remote
127 Fossil instance says, “I’ve already got that one, thanks,” and
128 ignores the push. Thus, short of breaking into the remote server
129 and modifying the repository in place, you couldn’t even make use of
130 a preimage attack if you had that power. This is an attack on the
131 server itself, not on Fossil’s data structures, so while it is
132 useful to think through this problem, it is not helpful to answering
133 our questions here.
134
135 The Fossil sync protocol also prevents the closest analog to Type 3
136 frauds in Fossil: copying a commit manifest in your local repo clone
137 won’t result in a double-commit on sync.
138
139 In the absence of digital signatures, Fossil’s [RBAC system][caps]
140 restricts Type 2 forgery to trusted committers. Thus once again
141 we’re reduced to an infosec problem, not a data structure design
142 question. (Inversely, enabling commit clearsigning is a good idea
 
 
143 if you have committers on your repo whom you don’t trust not to
144 commit Type 2 frauds. But let us be clear: your choice of setting
145 does not answer the question of whether Fossil is a blockchain.)
146
147 If Fossil signatures prevent Type 1 and Type 2 frauds, you
@@ -245,19 +247,22 @@
245 to change the value of existing commits (Type 1) or add new commits to
246 the repository (Type 2).
247
248 What if we removed those features from Fossil, creating an append-only
249 Fossil variant? Is it a DLT then? Arguably still not, because [today’s Fossil
250 is an AP-mode system][ctap] in the [CAP theorem][cap] sense, which means
251 there can be no guaranteed consensus on the content of the ledger at any
252 given time. If you had an AP-mode accounts receivable system, it could
253 have different bottom-line totals at different sites, because you’ve
254 cast away “C” to get AP-mode operation.
 
 
255
256 Because of this, you could still not guarantee that the command
257 “`fossil info tip`” gives the same result everywhere. A CA or CP-mode Fossil
258 variant would guarantee that everyone got the same result. (Everyone not
 
259 partitioned away from the majority of the network at any rate, in the CP
260 case.)
261
262 What are the prospects for CA-mode or CP-mode Fossil? [We don’t want
263 CA-mode Fossil][ctca], but [CP-mode could be useful][ctcp]. Until the latter
@@ -366,13 +371,13 @@
366 commits into your repository under any name they want.
367
368 On the server side, you can also [scrub] the logging that remembers
369 where each commit came from.
370
371 That info isn’t transmitted from the remote server on clone or pull.
372 Instead, the size of the `rcvfrom` table after initial clone is 1: it
373 contains the remote server’s IP address. On each pull containing new
374 artifacts, your local `fossil` instance adds another entry to this
375 table, likely with the same IP address unless the server has moved or
376 you’re using [multiple remotes][mrep]. This table is far more
377 interesting on the server side, containing the IP addresses of all
378 contentful pushes; thus [the `scrub` command][scrub].
@@ -452,18 +457,14 @@
452
453 # Conclusion
454
455 This author believes it is technologically indefensible to call Fossil a
456 “blockchain” in any sense likely to be understood by a majority of those
457 you’re communicating with.
458
459 Within a certain narrow scope, you can defend this usage, but if you do
460 that, you’ve failed any goal that requires clear communication: it
461 doesn’t work to use a term in a nonstandard way just because you can
462 defend it. The people you’re communicating your ideas to must have the
463 same concept of the terms you use.
464
465
466 What term should you use instead? Fossil stores a DAG of hash-chained
467 commits, so an indisputably correct term is a [Merkle tree][mt], named
468 after [its inventor][drrm]. You could also use the more generic term
469 “hash tree.”
470
--- www/blockchain.md
+++ www/blockchain.md
@@ -11,25 +11,24 @@
11
12 The [Wikipedia definition of "blockchain"][bcwp] begins:
13
14 >
15 "A blockchain…is a growing list of records, called blocks, which are linked using
16 cryptography… Each block contains a cryptographic hash of the previous
17 block, a timestamp, and transaction data (generally represented as a Merkle tree)."
18
19 Point-for-point, Fossil follows this partial definition.
20 The blocks
21 are Fossil’s ["manifest" artifacts](./fileformat.wiki#manifest). Each
22 manifest has a cryptographically-strong [SHA-1] or [SHA-3] hash linking it to
23 one or more “parent” blocks. The manifest also contains a timestamp and
24 the transactional data needed to express a commit to the repository.
25 To traverse the Fossil repository from the tips of its [DAG] to the
26 root by following the parent hashes in each manifest is to traverse
27 a Merkle tree.
 
28 Every change in Fossil starts by adding one or more manifests to
29 the repository, extending this Merkle tree.
30
31 [bcwp]: https://en.wikipedia.org/wiki/Blockchain
32 [DAG]: https://en.wikipedia.org/wiki/Directed_acyclic_graph
33 [SHA-1]: https://en.wikipedia.org/wiki/SHA-1
34 [SHA-3]: https://en.wikipedia.org/wiki/SHA-3
@@ -61,11 +60,12 @@
60 * **Type 2** is creation of new fraudulent currency that will pass
61 in commerce. To extend our analogy, it is the creation of new
62 US $10 bills. There are two sub-types to this fraud. In terms of
63 our analogy, they are:
64
65 * **Type 2a**: copying an existing legitimate $10 bill<p>
66
67 * **Type 2b**: printing a new $10 bill that is unlike an existing
68 legitimate one, yet which will still pass in commerce
69
70 * **Type 3** is double-spending existing legitimate cryptocurrency.
71 There is no analogy in paper money due to its physical form; it is a
@@ -92,11 +92,11 @@
92 cryptocurrencies add a separate chain of hashes to make checking
93 for double-spending quick and easy.
94
95 Fossil has [a disabled-by-default feature][cs] to call out to an
96 external copy of [PGP] or [GPG] to sign commit manifests before
97 inserting them into the repository. You can couple that with
98 a server-side [after-receive hook][arh] to reject unsigned commits.
99
100 Although there are several distinctions you can draw between the way
101 Fossil’s commit signing scheme works and the way block signing works
102 in cryptocurrencies, only one is of material interest for our
@@ -112,11 +112,11 @@
112 prevention, both Type 1 and Type 2. You cannot modify existing
113 commits (Type 1 forgery) because you do not have the original
114 committer’s private signing key, and you cannot forge new commits
115 attesting to come from some other trusted committer (Type 2) because
116 you don’t have any of their private signing keys, either.
117 Cryptocurrencies use the work problem to prevent Type 2
118 forgeries, but the application of that to Fossil is a matter we get
119 to [later](#work).
120
121 Although you have complete control over the contents of your local
122 Fossil repository clone, you cannot perform Type 1 forgery on its
@@ -124,24 +124,26 @@
124 algorithm. ([SHA3-256][SHA-3] by default in the current version of
125 Fossil.) Even if you could, Fossil’s sync protocol will prevent the
126 modification from being pushed into another repository: the remote
127 Fossil instance says, “I’ve already got that one, thanks,” and
128 ignores the push. Thus, short of breaking into the remote server
129 and modifying the repository in place, you couldn’t make use of
130 a preimage attack even if you had that power. Further, that would be an attack on the
131 server itself, not on Fossil’s data structures, so while it is
132 useful to think through this problem, it is not helpful in answering
133 our questions here.
134
135 The Fossil sync protocol’s duplication detection also prevents the closest analog to Type 3
136 frauds in Fossil: copying a commit manifest in your local repo clone
137 won’t result in a double-commit on sync.
138
139 In the absence of digital signatures, Fossil’s [RBAC system][caps]
140 restricts Type 2 forgery to trusted committers. Thus once again
141 we’re reduced to an infosec problem, not a data structure design
142 question.
143
144 (Inversely, enabling commit clearsigning is a good idea
145 if you have committers on your repo whom you don’t trust not to
146 commit Type 2 frauds. But let us be clear: your choice of setting
147 does not answer the question of whether Fossil is a blockchain.)
148
149 If Fossil signatures prevent Type 1 and Type 2 frauds, you
@@ -245,19 +247,22 @@
247 to change the value of existing commits (Type 1) or add new commits to
248 the repository (Type 2).
249
250 What if we removed those features from Fossil, creating an append-only
251 Fossil variant? Is it a DLT then? Arguably still not, because [today’s Fossil
252 is an AP-mode system][ctap], which means
253 there can be no guaranteed consensus on the content of the ledger at any
254 given time. An AP-mode accounts receivable system would allow
255 different bottom-line totals at different sites, because you’ve
256 cast away “C” to get AP-mode operation. (See the prior link or
257 [Wikipedia’s article on the CAP theorem][cap] if you aren’t following
258 this terminology.)
259
260 By the same token, you cannot guarantee that the command
261 “`fossil info tip`” gives the same result everywhere. You would need to
262 recast Fossil as a CA or CP-mode system to solve that.
263 (Everyone not
264 partitioned away from the majority of the network at any rate, in the CP
265 case.)
266
267 What are the prospects for CA-mode or CP-mode Fossil? [We don’t want
268 CA-mode Fossil][ctca], but [CP-mode could be useful][ctcp]. Until the latter
@@ -366,13 +371,13 @@
371 commits into your repository under any name they want.
372
373 On the server side, you can also [scrub] the logging that remembers
374 where each commit came from.
375
376 Commit source info isn’t transmitted from the remote server on clone or pull:
377 the size of the `rcvfrom` table after initial clone is 1, containing
378 only the remote server’s IP address. On each pull containing new
379 artifacts, your local `fossil` instance adds another entry to this
380 table, likely with the same IP address unless the server has moved or
381 you’re using [multiple remotes][mrep]. This table is far more
382 interesting on the server side, containing the IP addresses of all
383 contentful pushes; thus [the `scrub` command][scrub].
@@ -452,18 +457,14 @@
457
458 # Conclusion
459
460 This author believes it is technologically indefensible to call Fossil a
461 “blockchain” in any sense likely to be understood by a majority of those
462 you’re communicating with. Using a term in a nonstandard way just because you can
463 defend it means you’ve failed any goal that requires clear communication.
464 The people you’re communicating your ideas to must have the
 
 
 
465 same concept of the terms you use.
 
466
467 What term should you use instead? Fossil stores a DAG of hash-chained
468 commits, so an indisputably correct term is a [Merkle tree][mt], named
469 after [its inventor][drrm]. You could also use the more generic term
470 “hash tree.”
471
--- www/private.wiki
+++ www/private.wiki
@@ -31,11 +31,12 @@
3131
fossil update trunk
3232
fossil merge private
3333
fossil commit
3434
</pre></blockquote>
3535
36
-The private branch remains private, but all of the changes associated with
36
+The private branch remains private and is not recorded as a parent
37
+in the merge manifest's P-card, but all of the changes associated with
3738
the private branch are now folded into the public branch and are hence
3839
visible to other users of the project.
3940
4041
A private branch created with Fossil version 1.30 or newer can also be
4142
converted into a public branch using the <code>fossil publish</code>
4243
--- www/private.wiki
+++ www/private.wiki
@@ -31,11 +31,12 @@
31 fossil update trunk
32 fossil merge private
33 fossil commit
34 </pre></blockquote>
35
36 The private branch remains private, but all of the changes associated with
 
37 the private branch are now folded into the public branch and are hence
38 visible to other users of the project.
39
40 A private branch created with Fossil version 1.30 or newer can also be
41 converted into a public branch using the <code>fossil publish</code>
42
--- www/private.wiki
+++ www/private.wiki
@@ -31,11 +31,12 @@
31 fossil update trunk
32 fossil merge private
33 fossil commit
34 </pre></blockquote>
35
36 The private branch remains private and is not recorded as a parent
37 in the merge manifest's P-card, but all of the changes associated with
38 the private branch are now folded into the public branch and are hence
39 visible to other users of the project.
40
41 A private branch created with Fossil version 1.30 or newer can also be
42 converted into a public branch using the <code>fossil publish</code>
43

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button