压缩存储在big.Int?

时间:2018-02-09 00:41:43

标签: go compression

我需要将以太坊(加密货币)余额导出到Postgres,但我需要在blob中压缩它们,因为它们太多了,我必须为每个块存储状态。余额存储在big.Int,但大多数帐户的余额为0(或非常接近于零),所以我在考虑这种压缩算法:

Format (single record): 
    8bits:  the length of the bit string
    following bits : the actual big.Int converted into bits with Int.Bits() function

天平以1/10 ^ 18精度存储,因此1个以1位存储,18个零。将我的算法压缩成最好的方法吗?或者有更好的想法吗?

例如,另一个想法是选择一个float64,但我不确定它是否可以保存所有值的范围。 1以太是1,有18个零,但加密货币交换可以平衡百万个,所以最大值为1,大约25个零。或者我可以在最糟糕的情况下选择float128。

你有什么建议?

1 个答案:

答案 0 :(得分:2)

要获得最大压缩效果,请使用Bytes()(返回[]byte),而不是Bits()(返回[]uint)。例如,零余额(公共值)是一个字节的blob。此外,允许负余额。例如,

package main

import (
    "fmt"
    "math/big"
)

func CompressBalance(i *big.Int) []byte {
    if i == nil {
        return nil
    }
    if i.BitLen() == 0 {
        return []byte{0}
    }
    byts := i.Bytes()
    if len(byts) > 0x7F {
        return nil
    }
    blob := make([]byte, 1+len(byts))
    blob[0] = byte(len(byts))
    blob[0] |= byte(i.Sign()) & 0x80
    copy(blob[1:], byts)
    return blob
}

func DecompressBalance(b []byte) *big.Int {
    if len(b) <= 0 {
        return nil
    }
    if 1+int(b[0]&0x7F) != len(b) {
        return nil
    }
    i := new(big.Int)
    if b[0] == 0 {
        return i
    }
    i.SetBytes(b[1:])
    if b[0]&0x80 == 0x80 {
        i.Neg(i)
    }
    return i
}

func main() {
    tests := []string{
        "0",
        "1925000288124900513257758",  // 1,925,000.288124900513257758
        "-1925000288124900513257758", // -1,925,000.288124900513257758
    }
    for _, s := range tests {
        i := new(big.Int)
        i, ok := i.SetString(s, 10)
        if !ok {
            fmt.Println("error:", i, ok)
        }
        blob := CompressBalance(i)
        j := DecompressBalance(blob)
        fmt.Printf("i: %s\nj: %s\nblob: %d %v\n", i, j, len(blob), blob)
    }
}

游乐场:https://play.golang.org/p/zClfVxG6agL

输出:

i: 0
j: 0
blob: 1 [0]
i: 1925000288124900513257758
j: 1925000288124900513257758
blob: 12 [11 1 151 162 121 135 80 245 19 41 153 30]
i: -1925000288124900513257758
j: -1925000288124900513257758
blob: 12 [139 1 151 162 121 135 80 245 19 41 153 30]

金融交易需要确切的数字。根据设计,浮点数是近似值。