Skip to content

Commit

Permalink
Merge pull request #325 from OffchainLabs/cbrotli
Browse files Browse the repository at this point in the history
use cbrotli
  • Loading branch information
tsahee authored Mar 10, 2022
2 parents a3979ba + cbd9664 commit c5f122e
Show file tree
Hide file tree
Showing 27 changed files with 1,226 additions and 117 deletions.
32 changes: 32 additions & 0 deletions .github/workflows/arbitrator-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,38 @@ jobs:
make -j
make install
- name: Cache cbrotli
uses: actions/cache@v2
id: cache-cbrotli
with:
path: |
target/include/brotli/
target/lib-wasm/
target/lib/libbrotlicommon-static.a
target/lib/libbrotlienc-static.a
target/lib/libbrotlidec-static.a
key: ${{ runner.os }}-brotli-${{ hashFiles('build-brotli.sh') }}-${{ hashFiles('.github/workflows/arbitrator-ci.yaml') }}
restore-keys: ${{ runner.os }}-brotli-

- name: Build cbrotli-local
if: steps.cache-cbrotli.outputs.cache-hit != 'true'
run: ./build-brotli.sh -l

- name: Setup emsdk
if: steps.cache-cbrotli.outputs.cache-hit != 'true'
uses: mymindstorm/setup-emsdk@v11
with:
# Make sure to set a version number!
version: 3.1.6
# This is the name of the cache folder.
# The cache folder will be placed in the build directory,
# so make sure it doesn't conflict with anything!
actions-cache-folder: 'emsdk-cache'

- name: Build cbrotli-wasm
if: steps.cache-cbrotli.outputs.cache-hit != 'true'
run: ./build-brotli.sh -w

- name: Add wabt to path
run: echo "$HOME/wabt-prefix/bin" >> "$GITHUB_PATH"

Expand Down
64 changes: 64 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,38 @@ jobs:
key: ${{ runner.os }}-lint-${{ hashFiles('**/go.sum') }}
restore-keys: ${{ runner.os }}-go-

- name: Cache cbrotli
uses: actions/cache@v2
id: cache-cbrotli
with:
path: |
target/include/brotli/
target/lib-wasm/
target/lib/libbrotlicommon-static.a
target/lib/libbrotlienc-static.a
target/lib/libbrotlidec-static.a
key: ${{ runner.os }}-brotli-${{ hashFiles('build-brotli.sh') }}-${{ hashFiles('.github/workflows/arbitrator-ci.yaml') }}
restore-keys: ${{ runner.os }}-brotli-

- name: Build cbrotli-local
if: steps.cache-cbrotli.outputs.cache-hit != 'true'
run: ./build-brotli.sh -l

- name: Setup emsdk
if: steps.cache-cbrotli.outputs.cache-hit != 'true'
uses: mymindstorm/setup-emsdk@v11
with:
# Make sure to set a version number!
version: 3.1.6
# This is the name of the cache folder.
# The cache folder will be placed in the build directory,
# so make sure it doesn't conflict with anything!
actions-cache-folder: 'emsdk-cache'

- name: Build cbrotli-wasm
if: steps.cache-cbrotli.outputs.cache-hit != 'true'
run: ./build-brotli.sh -w

- name: Build all lint dependencies
run: make -j build-node-deps

Expand Down Expand Up @@ -151,6 +183,38 @@ jobs:
key: ${{ runner.os }}-cargo-min-${{ hashFiles('arbitrator/Cargo.lock') }}
restore-keys: ${{ runner.os }}-cargo-

- name: Cache cbrotli
uses: actions/cache@v2
id: cache-cbrotli
with:
path: |
target/include/brotli/
target/lib-wasm/
target/lib/libbrotlicommon-static.a
target/lib/libbrotlienc-static.a
target/lib/libbrotlidec-static.a
key: ${{ runner.os }}-brotli-${{ hashFiles('build-brotli.sh') }}-${{ hashFiles('.github/workflows/arbitrator-ci.yaml') }}
restore-keys: ${{ runner.os }}-brotli-

- name: Build cbrotli-local
if: steps.cache-cbrotli.outputs.cache-hit != 'true'
run: ./build-brotli.sh -l

- name: Setup emsdk
if: steps.cache-cbrotli.outputs.cache-hit != 'true'
uses: mymindstorm/setup-emsdk@v11
with:
# Make sure to set a version number!
version: 3.1.6
# This is the name of the cache folder.
# The cache folder will be placed in the build directory,
# so make sure it doesn't conflict with anything!
actions-cache-folder: 'emsdk-cache'

- name: Build cbrotli-wasm
if: steps.cache-cbrotli.outputs.cache-hit != 'true'
run: ./build-brotli.sh -w

- name: Build
run: make build test-go-deps -j

Expand Down
32 changes: 30 additions & 2 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,3 +1,23 @@
FROM emscripten/emsdk:3.1.7 as brotli-wasm-builder
WORKDIR /workspace
COPY build-brotli.sh .
RUN apt-get update && \
apt-get install -y cmake make git && \
./build-brotli.sh -w -t install/

FROM scratch as brotli-wasm-export
COPY --from=brotli-wasm-builder /workspace/install/ /

FROM debian:bullseye-slim as brotli-library-builder
WORKDIR /workspace
COPY build-brotli.sh .
RUN apt-get update && \
apt-get install -y cmake make gcc git && \
./build-brotli.sh -l -t install/

FROM scratch as brotli-library-export
COPY --from=brotli-library-builder /workspace/install/ /

FROM node:17-bullseye-slim as contracts-builder
RUN apt-get update && \
apt-get install -y git python3 make g++
Expand All @@ -16,6 +36,7 @@ RUN export DEBIAN_FRONTEND=noninteractive && \
rustup target add wasm32-wasi
COPY ./Makefile ./
COPY arbitrator/wasm-libraries arbitrator/wasm-libraries/
COPY --from=brotli-wasm-export / target/
RUN make build-wasm-libs

FROM rust:1.57-slim-bullseye as prover-header-builder
Expand All @@ -29,6 +50,9 @@ COPY ./Makefile ./
COPY arbitrator/prover arbitrator/prover
RUN make build-prover-header

FROM scratch as prover-header-export
COPY --from=prover-header-builder /workspace/target/ /

FROM rust:1.57-slim-bullseye as prover-lib-builder
WORKDIR /workspace
RUN export DEBIAN_FRONTEND=noninteractive && \
Expand All @@ -44,6 +68,9 @@ COPY arbitrator/prover arbitrator/prover
RUN touch -a -m arbitrator/prover/src/lib.rs && \
make build-prover-lib

FROM scratch as prover-lib-export
COPY --from=prover-lib-builder /workspace/target/ /

FROM golang:1.17-bullseye as node-builder
COPY go.mod go.sum /workspace/
WORKDIR /workspace
Expand All @@ -57,8 +84,9 @@ COPY go-ethereum go-ethereum/
RUN mkdir -p solgen/go/ && \
go run -v solgen/gen.go
COPY . ./
COPY --from=prover-header-builder /workspace/target/ target/
COPY --from=prover-lib-builder /workspace/target/ target/
COPY --from=prover-header-export / target/
COPY --from=prover-lib-export / target/
COPY --from=brotli-library-export / target/
RUN mkdir -p target/bin && \
go build -v -o target/bin ./cmd/node ./cmd/deploy && \
GOOS=js GOARCH=wasm go build -o res/target/lib/replay.wasm ./cmd/replay/...
Expand Down
25 changes: 23 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ replay_wasm=$(output_root)/lib/replay.wasm

arbitrator_generated_header=$(output_root)/include/arbitrator.h
arbitrator_wasm_libs_nogo=$(output_root)/lib/wasi_stub.wasm $(output_root)/lib/host_io.wasm $(output_root)/lib/soft-float.wasm
arbitrator_wasm_libs=$(arbitrator_wasm_libs_nogo) $(output_root)/lib/go_stub.wasm
arbitrator_wasm_libs=$(arbitrator_wasm_libs_nogo) $(output_root)/lib/go_stub.wasm $(output_root)/lib/brotli.wasm
arbitrator_prover_lib=$(output_root)/lib/libprover.a
arbitrator_prover_bin=$(output_root)/bin/prover

Expand Down Expand Up @@ -49,7 +49,7 @@ all: build build-replay-env test-gen-proofs
build: $(output_root)/bin/node
@printf $(done)

build-node-deps: $(go_source) $(das_rpc_files) build-prover-header build-prover-lib .make/solgen
build-node-deps: $(go_source) $(das_rpc_files) build-prover-header build-prover-lib .make/solgen .make/cbrotli-lib

test-go-deps: \
build-replay-env \
Expand Down Expand Up @@ -238,6 +238,11 @@ $(output_root)/lib/host_io.wasm: arbitrator/wasm-libraries/host-io/src/**
cargo build --manifest-path arbitrator/wasm-libraries/Cargo.toml --release --target wasm32-wasi --package host-io
install arbitrator/wasm-libraries/target/wasm32-wasi/release/host_io.wasm $@

$(output_root)/lib/brotli.wasm: arbitrator/wasm-libraries/brotli/src/** .make/cbrotli-wasm
mkdir -p $(output_root)/lib
cargo build --manifest-path arbitrator/wasm-libraries/Cargo.toml --release --target wasm32-wasi --package brotli
install arbitrator/wasm-libraries/target/wasm32-wasi/release/brotli.wasm $@

arbitrator/prover/test-cases/%.wasm: arbitrator/prover/test-cases/%.wat
wat2wasm $< -o $@

Expand Down Expand Up @@ -283,6 +288,22 @@ solgen/test/prover/proofs/%.json: arbitrator/prover/test-cases/%.wasm $(arbitrat
yarn --cwd solgen install
@touch $@

.make/cbrotli-lib: | .make
@printf "%btesting cbrotli local build exists. If this step fails, see ./build-brotli.sh -l -h%b\n" $(color_pink) $(color_reset)
test -f target/include/brotli/encode.h
test -f target/include/brotli/decode.h
test -f target/lib/libbrotlicommon-static.a
test -f target/lib/libbrotlienc-static.a
test -f target/lib/libbrotlidec-static.a
@touch $@

.make/cbrotli-wasm: | .make
@printf "%btesting cbrotli wasm build exists. If this step fails, see ./build-brotli.sh -w -h%b\n" $(color_pink) $(color_reset)
test -f target/lib-wasm/libbrotlicommon-static.a
test -f target/lib-wasm/libbrotlienc-static.a
test -f target/lib-wasm/libbrotlidec-static.a
@touch $@

.make:
mkdir .make

Expand Down
48 changes: 48 additions & 0 deletions arbcompress/compress_cgo.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
//go:build !js
// +build !js

package arbcompress

/*
#cgo CFLAGS: -g -Wall -I${SRCDIR}/../target/include/
#cgo LDFLAGS: ${SRCDIR}/../target/lib/libbrotlidec-static.a ${SRCDIR}/../target/lib/libbrotlienc-static.a ${SRCDIR}/../target/lib/libbrotlicommon-static.a -lm
#include "brotli/encode.h"
#include "brotli/decode.h"
*/
import "C"
import (
"fmt"
)

func Decompress(input []byte, maxSize int) ([]byte, error) {
outbuf := make([]byte, maxSize)
outsize := C.size_t(maxSize)
res := C.BrotliDecoderDecompress(C.size_t(len(input)), (*C.uint8_t)(&input[0]), &outsize, (*C.uint8_t)(&outbuf[0]))
if res != 1 {
return nil, fmt.Errorf("failed decompression: %d", res)
}
if int(outsize) > maxSize {
return nil, fmt.Errorf("result too large: %d", outsize)
}
return outbuf[:outsize], nil
}

func compressLevel(input []byte, level int) ([]byte, error) {
maxOutSize := compressedBufferSizeFor(len(input))
outbuf := make([]byte, maxOutSize)
outSize := C.size_t(maxOutSize)
var inputPtr *C.uint8_t
if len(input) > 0 {
inputPtr = (*C.uint8_t)(&input[0])
}
res := C.BrotliEncoderCompress(C.int(level), C.BROTLI_DEFAULT_WINDOW, C.BROTLI_MODE_GENERIC,
C.size_t(len(input)), inputPtr, &outSize, (*C.uint8_t)(&outbuf[0]))
if res != 1 {
return nil, fmt.Errorf("failed compression: %d", res)
}
return outbuf[:outSize], nil
}

func CompressWell(input []byte) ([]byte, error) {
return compressLevel(input, LEVEL_WELL)
}
13 changes: 13 additions & 0 deletions arbcompress/compress_common.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package arbcompress

const LEVEL_FAST = 0
const LEVEL_WELL = 11
const WINDOW_SIZE = 22 // BROTLI_DEFAULT_WINDOW

func compressedBufferSizeFor(len int) int {
return len + (len>>10)*8 + 64 // actual limit is: len + (len >> 14) * 4 + 6
}

func CompressFast(input []byte) ([]byte, error) {
return compressLevel(input, LEVEL_FAST)
}
47 changes: 47 additions & 0 deletions arbcompress/compress_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package arbcompress

import (
"bytes"
"testing"

"github.com/offchainlabs/nitro/util/testhelpers"
)

func testDecompress(t *testing.T, compressed, decompressed []byte) {
res, err := Decompress(compressed, len(decompressed)*2+64)
if err != nil {
t.Fatal(err)
}
if !bytes.Equal(res, decompressed) {
t.Fatal("results differ ", res, " vs. ", decompressed)
}
}

func testCompressDecompress(t *testing.T, data []byte) {
compressedWell, err := CompressWell(data)
if err != nil {
t.Fatal(err)
}
testDecompress(t, compressedWell, data)

compressedFast, err := CompressFast(data)
if err != nil {
t.Fatal(err)
}
testDecompress(t, compressedFast, data)
}

func TestArbCompress(t *testing.T) {
asciiData := []byte("This is a long and repetitive string. Yadda yadda yadda yadda yadda. The quick brown fox jumped over the lazy dog.")
for i := 0; i < 8; i++ {
asciiData = append(asciiData, asciiData...)
}
testCompressDecompress(t, asciiData)

source := testhelpers.NewPseudoRandomDataSource(t, 0)
randData := source.GetData(2500)
testCompressDecompress(t, randData)

// test empty data:
testCompressDecompress(t, []byte{})
}
31 changes: 31 additions & 0 deletions arbcompress/compress_wasm.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
//go:build js
// +build js

package arbcompress

import (
"fmt"
)

func brotliCompress(inBuf []byte, outBuf []byte, level int, windowSize int) int64

func brotliDecompress(inBuf []byte, outBuf []byte) int64

func Decompress(input []byte, maxSize int) ([]byte, error) {
outBuf := make([]byte, maxSize)
outLen := brotliDecompress(input, outBuf)
if outLen < 0 {
return nil, fmt.Errorf("failed decompression")
}
return outBuf[:outLen], nil
}

func compressLevel(input []byte, level int) ([]byte, error) {
maxOutSize := compressedBufferSizeFor(len(input))
outBuf := make([]byte, maxOutSize)
outLen := brotliCompress(input, outBuf, level, WINDOW_SIZE)
if outLen < 0 {
return nil, fmt.Errorf("failed compression")
}
return outBuf[:outLen], nil
}
16 changes: 16 additions & 0 deletions arbcompress/raw.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
//
// Copyright 2021, Offchain Labs, Inc. All rights reserved.
//

//go:build js
// +build js

#include "textflag.h"

TEXT ·brotliCompress(SB), NOSPLIT, $0
CallImport
RET

TEXT ·brotliDecompress(SB), NOSPLIT, $0
CallImport
RET
Loading

0 comments on commit c5f122e

Please sign in to comment.