Blockchain Tables in Oracle Database 21c
A blockchain table is a tamper-proof, insert-only table with an associated table-level and row-level retention period.
oracle 21cconfigurationintermediate
by OracleDba
60 views
A blockchain table is a tamper-proof, insert-only table with an associated table-level and row-level retention period.
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071
NO DROP [ UNTIL number DAYS IDLE ]
NO DELETE { [ LOCKED ] | (UNTIL number DAYS AFTER INSERT [ LOCKED ]) }
HASHING USING sha2_512 VERSION v1
--drop table bct_t1 purge;
create blockchain table bct_t1 (
id number,
fruit varchar2(20),
quantity number,
created_date date,
constraint bct_t1_pk primary key (id)
)
no drop until 0 days idle
no delete until 16 days after insert
hashing using "SHA2_512" version "v1";
set linesize 120 pagesize 50
column column_name format a30
column data_type format a27
column hidden_column format a13
select internal_column_id,
column_name,
data_type,
data_length,
hidden_column
FROM user_tab_cols
WHERE table_name = 'BCT_T1'
ORDER BY internal_column_id;
INTERNAL_COLUMN_ID COLUMN_NAME DATA_TYPE DATA_LENGTH HIDDEN_COLUMN
------------------ ------------------------------ --------------------------- ----------- -------------
1 ID NUMBER 22 NO
2 FRUIT VARCHAR2 25 NO
3 QUANTITY NUMBER 22 NO
4 CREATED_DATE DATE 7 NO
5 ORABCTAB_INST_ID$ NUMBER 22 YES
6 ORABCTAB_CHAIN_ID$ NUMBER 22 YES
7 ORABCTAB_SEQ_NUM$ NUMBER 22 YES
8 ORABCTAB_CREATION_TIME$ TIMESTAMP(6) WITH TIME ZONE 13 YES
9 ORABCTAB_USER_NUMBER$ NUMBER 22 YES
10 ORABCTAB_HASH$ RAW 2000 YES
11 ORABCTAB_SIGNATURE$ RAW 2000 YES
12 ORABCTAB_SIGNATURE_ALG$ NUMBER 22 YES
13 ORABCTAB_SIGNATURE_CERT$ RAW 16 YES
14 ORABCTAB_SPARE$ RAW 2000 YES
14 rows selected.
SQL>
column row_retention format a13
column row_retention_locked format a20
column table_inactivity_retention format a26
column hash_algorithm format a14
SELECT row_retention,
row_retention_locked,
table_inactivity_retention,
hash_algorithm
FROM user_blockchain_tables
WHERE table_name = 'BCT_T1';
ROW_RETENTION ROW_RETENTION_LOCKED TABLE_INACTIVITY_RETENTION HASH_ALGORITHM
------------- -------------------- -------------------------- --------------
16 NO 0 SHA2_512
SQL>12345678910111213141516171819202122232425262728293031323334
alter table bct_t1 no drop until 100 days idle;
Error report -
ORA-05732: retention value cannot be lowered
SQL>
alter table bct_t1 no drop;
Error starting at line : 1 in command -
alter table bct_t1 no drop
Error report -
ORA-00600: internal error code, arguments: [atbbctable_1], [0], [], [], [], [], [], [], [], [], [], []
-- Increase to 32 days.
alter table bct_t1 no delete until 32 days after insert;
Table BCT_T1 altered.
SQL>
-- Decrease to 16 days (fail).
alter table bct_t1 no delete until 16 days after insert;
Error report -
ORA-05732: retention value cannot be lowered
SQL>
alter table bct_t1 no delete;
Error report -
ORA-00600: internal error code, arguments: [atbbctable_1], [0], [], [], [], [], [], [], [], [], [], []123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960
-- INSERT
insert into bct_t1 (id, fruit, quantity, created_date ) values (1, 'apple', 20, sysdate);
1 row inserted.
SQL> commit;
Commit complete.
SQL>
-- UPDATE
update bct_t1 set quantity = 10 where id = 1;
Error report -
SQL Error: ORA-05715: operation not allowed on the blockchain table
SQL>
-- DELETE
delete from bct_t1 where id = 1;
Error report -
SQL Error: ORA-05715: operation not allowed on the blockchain table
SQL>
truncate table bct_t1;
Error report -
ORA-05715: operation not allowed on the blockchain table
SQL>
-- Extend column.
alter table bct_t1 modify (fruit varchar2(25));
Table BCT_T1 altered.
SQL>
-- Add column
alter table bct_t1 add (additional_info varchar2(50));
Error report -
ORA-05715: operation not allowed on the blockchain table
SQL>
-- Drop column.
alter table bct_t1 drop column quantity;
Error report -
ORA-05715: operation not allowed on the blockchain table
SQL>123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960
set serveroutput on
declare
l_rows number;
begin
dbms_blockchain_table.delete_expired_rows(
schema_name => 'testuser1',
table_name => 'bct_t1',
before_timestamp => null,
number_of_rows_deleted => l_rows);
dbms_output.put_line('Rows Deleted=' || l_rows);
end;
/
Rows Deleted=0
PL/SQL procedure successfully completed.
SQL>
set serveroutput on
declare
l_rows number;
begin
dbms_blockchain_table.delete_expired_rows(
schema_name => 'testuser1',
table_name => 'bct_t1',
before_timestamp => systimestamp - 60,
number_of_rows_deleted => l_rows);
dbms_output.put_line('Rows Deleted=' || l_rows);
end;
/
Rows Deleted=0
PL/SQL procedure successfully completed.
SQL>
set serveroutput on
declare
l_rows number;
l_verified number;
begin
select count(*)
into l_rows
from testuser1.bct_t1;
dbms_blockchain_table.verify_rows(
schema_name => 'testuser1',
table_name => 'bct_t1',
number_of_rows_verified => l_verified);
dbms_output.put_line('Rows=' || l_rows || ' Verified Rows=' || l_verified);
end;
/
Rows=1 Verified Rows=1
PL/SQL procedure successfully completed.
SQL>1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677
mkdir /home/oracle/my_wallet
openssl req \
-newkey rsa:2048 -nodes -sha512 \
-x509 -days 3650 \
-outform der \
-keyout /home/oracle/my_wallet/my-bct-test-key.der \
-out /home/oracle/my_wallet/my-bct-test-cert.der \
-subj "/C=GB/ST=West Midlands/L=Birmingham/O=Example Company/OU=Devs/CN=Tim Hall/[email protected]"
conn sys/SysPassword1@//localhost:1521/freepdb1 as sysdba
create or replace directory cert_dir as '/home/oracle/my_wallet/';
grant read, write on directory cert_dir to testuser1;
conn testuser1/testuser1@//localhost:1521/freepdb1
set serveroutput on
declare
l_dir varchar2(20) := 'CERT_DIR';
l_file_name varchar2(20) := 'id_1_signature.dat';
l_cert blob;
l_bfile bfile;
l_destoffset integer := 1;
l_srcoffset integer := 1;
l_cert_id raw(16);
begin
dbms_lob.createtemporary(l_cert, false);
l_bfile := bfilename(l_dir, l_file_name);
if (dbms_lob.fileexists( l_bfile ) = 1) then
dbms_lob.fileopen( l_bfile );
dbms_lob.loadblobfromfile(
dest_lob => l_cert,
src_bfile => l_bfile,
amount => dbms_lob.getlength(l_bfile),
dest_offset => l_destoffset,
src_offset => l_srcoffset
);
dbms_lob.fileclose( l_bfile );
dbms_user_certs.add_certificate(l_cert, l_cert_id);
dbms_output.put_line('certificate ID: ' || l_cert_id);
else
raise_application_error(-20001, 'must create the user certificates first');
end if;
end;
/
certificate ID: 006EA851A3FE2E89E065000000000001
PL/SQL procedure successfully completed.
SQL>
column certificate_id format a35
column user_name format a10
column distinguished_name format a30
select certificate_id,
user_name,
distinguished_name
from user_certificates;
CERTIFICATE_ID USER_NAME DISTINGUISHED_NAME
----------------------------------- ---------- ------------------------------
006EA851A3FE2E89E065000000000001 TESTUSER1 [email protected],CN=Tim Ha
ll,OU=Devs,O=Example Company,L
=Birmingham,ST=West Midlands,C
=GB
SQL>
begin
dbms_user_certs.drop_certificate(cert_id => '006EA851A3FE2E89E065000000000001');
end;
/123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
drop table if exists bct_sign purge;
create blockchain table bct_sign (
id number,
fruit varchar2(20),
quantity number,
created_date date,
constraint bct_sign_pk primary key (id)
)
no drop until 0 days idle
no delete until 16 days after insert
hashing using "SHA2_512" version "v2";
insert into bct_sign (id, fruit, quantity, created_date) values (1, 'apple', 20, sysdate);
commit;
declare
l_dir varchar2(20) := 'CERT_DIR';
l_file_name varchar2(20) := 'id_1_signature.dat';
l_row_data blob;
l_buffer raw(4000);
l_inst_id binary_integer;
l_chain_id binary_integer;
l_seq_num binary_integer;
l_row_len binary_integer;
l_file utl_file.file_type;
begin
select orabctab_inst_id$, orabctab_chain_id$, orabctab_seq_num$
into l_inst_id, l_chain_id, l_seq_num
from bct_sign
where id = 1;
dbms_blockchain_table.get_bytes_for_row_signature(
schema_name => 'testuser1',
table_name => 'bct_sign',
instance_id => l_inst_id,
chain_id => l_chain_id,
sequence_id => l_seq_num,
data_format => 1,
row_data => l_row_data);
l_row_len := dbms_lob.getlength(l_row_data);
dbms_lob.read(l_row_data, l_row_len, 1, l_buffer);
l_file := utl_file.fopen(l_dir,l_file_name,'wb', 32767);
utl_file.put_raw(l_file, l_buffer, true);
utl_file.fclose(l_file);
end;
/
cd /home/oracle/my_wallet/
openssl dgst -sha512 \
-sign my-bct-test-key.der \
-out id_1_signature.dat.sha512 \
id_1_signature.dat
declare
l_dir varchar2(30) := 'CERT_DIR';
l_file_name varchar2(30) := 'id_1_signature.dat.sha512';
l_cert_id raw (16) := hextoraw('006EA851A3FE2E89E065000000000001');
l_inst_id binary_integer;
l_chain_id binary_integer;
l_sequence_no binary_integer;
l_hash raw(2000);
l_signature blob;
l_bfile bfile;
l_destoffset integer := 1;
l_srcoffset integer := 1;
begin
select orabctab_inst_id$, orabctab_chain_id$, orabctab_seq_num$, orabctab_hash$, orabctab_signature$
into l_inst_id, l_chain_id, l_sequence_no, l_hash, l_signature
from bct_sign
where id = 1;
if l_signature is not null then
raise_application_error(-20000, 'The row has already been signed.');
end if;
l_bfile := bfilename(l_dir, l_file_name);
if (dbms_lob.fileexists(l_bfile ) = 1) then
dbms_lob.createtemporary(l_signature, false);
dbms_lob.fileopen(l_bfile);
dbms_lob.loadblobfromfile(
dest_lob => l_signature,
src_bfile => l_bfile,
amount => dbms_lob.getlength(l_bfile),
dest_offset => l_destoffset,
src_offset => l_srcoffset
);
dbms_lob.fileclose(l_bfile);
dbms_blockchain_table.sign_row(
schema_name => 'testuser1',
table_name => 'bct_sign',
instance_id => l_inst_id,
chain_id => l_chain_id,
sequence_id => l_sequence_no,
hash => l_hash,
signature => l_signature,
certificate_guid => l_cert_id,
signature_algo => dbms_blockchain_table.sign_algo_rsa_sha2_512);
else
raise_application_error(-20001, 'must create the signature first');
end if;
end;
/
set linesize 120
column signature format a30
column cert_id format a35
select id,
fruit,
orabctab_signature$ as signature,
orabctab_signature_cert$ as cert_id
from bct_sign
where id = 1;
ID FRUIT SIGNATURE CERT_ID
---------- -------------------- ------------------------------ -----------------------------------
1 apple 240FB4F558B14DD035DBDD5E71012E 006EA851A3FE2E89E065000000000001
AB28775A47C7CC2720D6660B4F9F1B
DFE8F944FCD55AD7BE67400A82B0A8
C00281F405CD53401D85DF6272AE3E
1294A02B6901B6693515348482F7D5
5F861860FBF66ACB6DFB7C977DC87C
3F2C1A9C1ABFE79F30DD6F7AAA155F
4F4DCD3B37F6BDD4AEDED784B18E3A
0EAB72B23F53403
SQL>Please to add comments
No comments yet. Be the first to comment!