mirror of
https://github.com/FlipsideCrypto/dcrd.git
synced 2026-02-06 10:56:47 +00:00
chaincfg: Avoid block 1 subsidy codegen explosion.
chaincfg/v2 modified the Params type to contain the required payouts created by the miner of the block at height 1. However, it was discovered that, due to code generation issues of the Go compiler, this caused the package's weight (measured by github.com/jondot/goweight) to explode to 7.7 MB. This appears to be due to an enormous amount of function calls, all of which could panic, when building the large slice literal. This improves the compiled size of the package by using code generation techniques to optimize the memory layout and code transformation of the subsidy values each time a params function is called. A single string contains all scripts for subsidy payouts concatenated together, in hex encoding, and a slice contains the index in the script data and the required payout amount. This is iterated in a loop to create a []TokenPayout each time it is needed. The new size of the compiled package using Go 1.12.7 on OpenBSD/amd64 is 379 kB, a reduction of 7.32 MB, and about 5% of the original size.
This commit is contained in:
parent
666286f0a7
commit
f860883562
97
chaincfg/generatesubsidytables.go
Normal file
97
chaincfg/generatesubsidytables.go
Normal file
@ -0,0 +1,97 @@
|
||||
// Copyright (c) 2019 The Decred developers
|
||||
// Use of this source code is governed by an ISC
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//+build ignore
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/decred/dcrd/chaincfg/v2"
|
||||
)
|
||||
|
||||
type payout struct {
|
||||
offset int
|
||||
amount int64
|
||||
}
|
||||
|
||||
type payouts []payout
|
||||
|
||||
func (p payouts) GoString() string {
|
||||
var s strings.Builder
|
||||
s.WriteString("[]blockOnePayout{\n")
|
||||
for i := range p {
|
||||
s.WriteString("\t")
|
||||
s.WriteString(fmt.Sprintf("{offset: %#v, amount: %#v}", p[i].offset, p[i].amount))
|
||||
s.WriteString(",\n")
|
||||
}
|
||||
s.WriteString("}")
|
||||
return s.String()
|
||||
}
|
||||
|
||||
type printer func(format string, args ...interface{})
|
||||
|
||||
func main() {
|
||||
buf := new(bytes.Buffer)
|
||||
p := func(format string, args ...interface{}) {
|
||||
fmt.Fprintf(buf, format, args...)
|
||||
}
|
||||
|
||||
p("// autogenerated by generatesubsidytable.go; do not edit\n\n")
|
||||
p("package chaincfg\n")
|
||||
for _, g := range []struct {
|
||||
name string
|
||||
tokenPayouts []chaincfg.TokenPayout
|
||||
}{
|
||||
{"MainNetParams", chaincfg.MainNetSubsidyDefinition},
|
||||
{"TestNet3Params", chaincfg.TestNet3SubsidyDefinition},
|
||||
{"SimNetParams", chaincfg.SimNetSubsidyDefinition},
|
||||
{"RegNetParams", chaincfg.RegNetSubsidyDefinition},
|
||||
} {
|
||||
p("\n")
|
||||
defs(p, g.name, g.tokenPayouts)
|
||||
}
|
||||
|
||||
out, err := os.Create("subsidytables.go")
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
_, err = io.Copy(out, buf)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func defs(p printer, paramsName string, tokenPayouts []chaincfg.TokenPayout) {
|
||||
var scripts strings.Builder
|
||||
var payouts payouts
|
||||
var offset int
|
||||
for _, t := range tokenPayouts {
|
||||
if t.ScriptVersion != 0 {
|
||||
log.Fatalf("this tool only generates code where all scripts are version 0")
|
||||
}
|
||||
_, err := scripts.WriteString(hex.EncodeToString(t.Script))
|
||||
if err != nil {
|
||||
log.Panic(err)
|
||||
}
|
||||
offset += len(t.Script)
|
||||
payouts = append(payouts, payout{
|
||||
offset: offset,
|
||||
amount: t.Amount,
|
||||
})
|
||||
}
|
||||
|
||||
p("const blockOnePayoutScripts_%s = %#v\n\n", paramsName, scripts.String())
|
||||
p("var blockOnePayouts_%s = %#v\n\n", paramsName, payouts)
|
||||
p("func tokenPayouts_%s() []TokenPayout {\n"+
|
||||
"\treturn tokenPayouts(blockOnePayoutScripts_%[1]s, blockOnePayouts_%[1]s)\n"+
|
||||
"}\n", paramsName)
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@ -318,10 +318,6 @@ func RegNetParams() *Params {
|
||||
// Organization address is RcQR65gasxuzf7mUeBXeAux6Z37joPuUwUN
|
||||
OrganizationPkScript: hexDecode("a9146913bcc838bd0087fb3f6b3c868423d5e300078d87"),
|
||||
OrganizationPkScriptVersion: 0,
|
||||
BlockOneLedger: []TokenPayout{
|
||||
mustPayout("76a9147e4765ae88ba9ad5c9e4715c484e90b34d358d5188ac", 100000*1e8),
|
||||
mustPayout("76a91402fb1ac0137666d79165e13cecd403883615270788ac", 100000*1e8),
|
||||
mustPayout("76a91469de627d3231b14228653dd09cba75eeb872754288ac", 100000*1e8),
|
||||
},
|
||||
BlockOneLedger: tokenPayouts_RegNetParams(),
|
||||
}
|
||||
}
|
||||
|
||||
@ -203,10 +203,6 @@ func SimNetParams() *Params {
|
||||
// Organization address is ScuQxvveKGfpG1ypt6u27F99Anf7EW3cqhq
|
||||
OrganizationPkScript: hexDecode("a914cbb08d6ca783b533b2c7d24a51fbca92d937bf9987"),
|
||||
OrganizationPkScriptVersion: 0,
|
||||
BlockOneLedger: []TokenPayout{
|
||||
mustPayout("76a91494ff37a0ee4d48abc45f70474f9b86f9da69a70988ac", 100000*1e8),
|
||||
mustPayout("76a914a6753ebbc08e2553e7dd6d64bdead4bcbff4fcf188ac", 100000*1e8),
|
||||
mustPayout("76a9147aa3211c2ead810bbf5911c275c69cc196202bd888ac", 100000*1e8),
|
||||
},
|
||||
BlockOneLedger: tokenPayouts_SimNetParams(),
|
||||
}
|
||||
}
|
||||
|
||||
27
chaincfg/subsidy.go
Normal file
27
chaincfg/subsidy.go
Normal file
@ -0,0 +1,27 @@
|
||||
// Copyright (c) 2019 The Decred developers
|
||||
// Use of this source code is governed by an ISC
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package chaincfg
|
||||
|
||||
//go:generate go run -tags subsidydefs generatesubsidytables.go
|
||||
|
||||
type blockOnePayout struct {
|
||||
offset int
|
||||
amount int64
|
||||
}
|
||||
|
||||
func tokenPayouts(scriptsHex string, payouts []blockOnePayout) []TokenPayout {
|
||||
tokenPayouts := make([]TokenPayout, len(payouts))
|
||||
var offset int
|
||||
scripts := hexDecode(scriptsHex)
|
||||
for i := range payouts {
|
||||
tokenPayouts[i] = TokenPayout{
|
||||
ScriptVersion: 0,
|
||||
Script: scripts[offset:payouts[i].offset],
|
||||
Amount: payouts[i].amount,
|
||||
}
|
||||
offset = payouts[i].offset
|
||||
}
|
||||
return tokenPayouts
|
||||
}
|
||||
3173
chaincfg/subsidydefinitions.go
Normal file
3173
chaincfg/subsidydefinitions.go
Normal file
File diff suppressed because it is too large
Load Diff
3193
chaincfg/subsidytables.go
Normal file
3193
chaincfg/subsidytables.go
Normal file
File diff suppressed because one or more lines are too long
@ -204,9 +204,6 @@ func TestNet3Params() *Params {
|
||||
// Organization address is TcrypGAcGCRVXrES7hWqVZb5oLJKCZEtoL1.
|
||||
OrganizationPkScript: hexDecode("a914d585cd7426d25b4ea5faf1e6987aacfeda3db94287"),
|
||||
OrganizationPkScriptVersion: 0,
|
||||
BlockOneLedger: []TokenPayout{
|
||||
mustPayout("76a914bb56576997d9f7abeebac585821b4d9a79d7ea0a88ac", 80000*1e8),
|
||||
mustPayout("76a9147a5c4cca76f2e0b36db4763daacbd6cbb6ee6e7b88ac", 20000*1e8),
|
||||
},
|
||||
BlockOneLedger: tokenPayouts_TestNet3Params(),
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user