Skip to content

Commit

Permalink
Merge pull request ethereum#373 from XinFinOrg/dev-upgrade
Browse files Browse the repository at this point in the history
CICD Improvement
Dynamic Masternodes and Dynamic V2 Vote threshold
Hardhat: Upgradeable Proxy support for XDC
Bug Fix on API
Supports the latest hardhat
  • Loading branch information
liam-lai authored Dec 1, 2023
2 parents 6cf9984 + 47bfdf7 commit 5a9edbd
Show file tree
Hide file tree
Showing 95 changed files with 4,296 additions and 2,693 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -52,3 +52,4 @@ coverage.txt
go.sum
cicd/devnet/terraform/.terraform*
cicd/devnet/tmp
.env
9 changes: 9 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -111,9 +111,13 @@ jobs:
before_script:
- echo "$DOCKER_PASSWORD" | docker login -u "$DOCKER_USERNAME" --password-stdin
- docker --version # document the version travis is using
- docker pull xinfinorg/devnet:latest # build the "previous" tag so that our devnet environment can run with both old and new code at the same time.
- docker tag xinfinorg/devnet:latest xinfinorg/devnet:previous
- docker rmi xinfinorg/devnet:latest
- docker build -t xinfinorg/devnet:latest -f cicd/Dockerfile .
script:
- docker push xinfinorg/devnet:latest
- docker push xinfinorg/devnet:previous

- stage: (Devnet)Terraform plan
if: branch = dev-upgrade AND type = push AND tag IS blank
Expand Down Expand Up @@ -168,3 +172,8 @@ jobs:
aws ecs update-service --region ap-southeast-2 --cluster devnet-xdcnode-cluster --service ecs-service-xdc$i --force-new-deployment --no-cli-pager;
done
- stage: (Devnet) Send Deployment Notification
if: branch = dev-upgrade AND type = push AND tag IS blank
language: bash
script:
- curl --location --request POST "66.94.98.186:8080/deploy?environment=devnet&service=xdc&version=$TRAVIS_COMMIT"
8 changes: 4 additions & 4 deletions XDCx/XDCx.go
Original file line number Diff line number Diff line change
Expand Up @@ -310,10 +310,10 @@ func (XDCx *XDCX) ConvertXDCToToken(chain consensus.ChainContext, statedb *state
}

// there are 3 tasks need to complete to update data in SDK nodes after matching
// 1. txMatchData.Order: order has been processed. This order should be put to `orders` collection with status sdktypes.OrderStatusOpen
// 2. txMatchData.Trades: includes information of matched orders.
// a. PutObject them to `trades` collection
// b. Update status of regrading orders to sdktypes.OrderStatusFilled
// 1. txMatchData.Order: order has been processed. This order should be put to `orders` collection with status sdktypes.OrderStatusOpen
// 2. txMatchData.Trades: includes information of matched orders.
// a. PutObject them to `trades` collection
// b. Update status of regrading orders to sdktypes.OrderStatusFilled
func (XDCx *XDCX) SyncDataToSDKNode(takerOrderInTx *tradingstate.OrderItem, txHash common.Hash, txMatchTime time.Time, statedb *state.StateDB, trades []map[string]string, rejectedOrders []*tradingstate.OrderItem, dirtyOrderCount *uint64) error {
var (
// originTakerOrder: order get from db, nil if it doesn't exist
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[
{
"name": "tfXdcNode",
"image": "xinfinorg/${xdc_environment}:${image_tag}",
"image": "xinfinorg/${image_environment}:${image_tag}",
"environment": [
{"name": "PRIVATE_KEYS", "value": "${private_keys}"},
{"name": "LOG_LEVEL", "value": "${log_level}"},
Expand Down
2 changes: 1 addition & 1 deletion cicd/devnet/terraform/module/region/ecs.tf
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ data template_file devnet_container_definition {
template = "${file("${path.module}/container-definition.tpl")}"

vars = {
xdc_environment = "devnet"
image_environment = "${lookup(each.value, "imageEnvironment", "devnet")}"
image_tag = "${lookup(each.value, "imageTag", "latest")}"
node_name = "${each.key}"
private_keys = "${each.value.pk}"
Expand Down
1 change: 1 addition & 0 deletions cmd/XDC/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,7 @@ var (
utils.RPCEnabledFlag,
utils.RPCListenAddrFlag,
utils.RPCPortFlag,
utils.RPCHttpWriteTimeoutFlag,
utils.RPCApiFlag,
utils.WSEnabledFlag,
utils.WSListenAddrFlag,
Expand Down
1 change: 1 addition & 0 deletions cmd/XDC/usage.go
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,7 @@ var AppHelpFlagGroups = []flagGroup{
utils.RPCEnabledFlag,
utils.RPCListenAddrFlag,
utils.RPCPortFlag,
utils.RPCHttpWriteTimeoutFlag,
utils.RPCApiFlag,
utils.WSEnabledFlag,
utils.WSListenAddrFlag,
Expand Down
74 changes: 44 additions & 30 deletions cmd/faucet/faucet.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ import (
"github.com/XinFinOrg/XDPoSChain/p2p/discv5"
"github.com/XinFinOrg/XDPoSChain/p2p/nat"
"github.com/XinFinOrg/XDPoSChain/params"
"golang.org/x/net/websocket"
"github.com/gorilla/websocket"
)

var (
Expand Down Expand Up @@ -204,14 +204,21 @@ type faucet struct {
nonce uint64 // Current pending nonce of the faucet
price *big.Int // Current gas price to issue funds with

conns []*websocket.Conn // Currently live websocket connections
conns []*wsConn // Currently live websocket connections
timeouts map[string]time.Time // History of users and their funding timeouts
reqs []*request // Currently pending funding requests
update chan struct{} // Channel to signal request updates

lock sync.RWMutex // Lock protecting the faucet's internals
}

// wsConn wraps a websocket connection with a write mutex as the underlying
// websocket library does not synchronize access to the stream.
type wsConn struct {
conn *websocket.Conn
wlock sync.Mutex
}

func newFaucet(genesis *core.Genesis, port int, enodes []*discv5.Node, network uint64, stats string, ks *keystore.KeyStore, index []byte) (*faucet, error) {
// Assemble the raw devp2p protocol stack
stack, err := node.New(&node.Config{
Expand Down Expand Up @@ -289,7 +296,7 @@ func (f *faucet) listenAndServe(port int) error {
go f.loop()

http.HandleFunc("/", f.webHandler)
http.Handle("/api", websocket.Handler(f.apiHandler))
http.HandleFunc("/api", f.apiHandler)

return http.ListenAndServe(fmt.Sprintf(":%d", port), nil)
}
Expand All @@ -301,18 +308,24 @@ func (f *faucet) webHandler(w http.ResponseWriter, r *http.Request) {
}

// apiHandler handles requests for Ether grants and transaction statuses.
func (f *faucet) apiHandler(conn *websocket.Conn) {
func (f *faucet) apiHandler(w http.ResponseWriter, r *http.Request) {
upgrader := websocket.Upgrader{}
conn, err := upgrader.Upgrade(w, r, nil)
if err != nil {
return
}
// Start tracking the connection and drop at the end
defer conn.Close()

f.lock.Lock()
f.conns = append(f.conns, conn)
wsconn := &wsConn{conn: conn}
f.conns = append(f.conns, wsconn)
f.lock.Unlock()

defer func() {
f.lock.Lock()
for i, c := range f.conns {
if c == conn {
if c.conn == conn {
f.conns = append(f.conns[:i], f.conns[i+1:]...)
break
}
Expand All @@ -324,7 +337,6 @@ func (f *faucet) apiHandler(conn *websocket.Conn) {
head *types.Header
balance *big.Int
nonce uint64
err error
)
for {
// Attempt to retrieve the stats, may error on no faucet connectivity
Expand All @@ -340,7 +352,7 @@ func (f *faucet) apiHandler(conn *websocket.Conn) {

// If stats retrieval failed, wait a bit and retry
if err != nil {
if err = sendError(conn, errors.New("Faucet offline: "+err.Error())); err != nil {
if err = sendError(wsconn, errors.New("Faucet offline: "+err.Error())); err != nil {
log.Warn("Failed to send faucet error to client", "err", err)
return
}
Expand All @@ -351,7 +363,7 @@ func (f *faucet) apiHandler(conn *websocket.Conn) {
break
}
// Send over the initial stats and the latest header
if err = send(conn, map[string]interface{}{
if err = send(wsconn, map[string]interface{}{
"funds": balance.Div(balance, ether),
"funded": nonce,
"peers": f.stack.Server().PeerCount(),
Expand All @@ -360,7 +372,7 @@ func (f *faucet) apiHandler(conn *websocket.Conn) {
log.Warn("Failed to send initial stats to client", "err", err)
return
}
if err = send(conn, head, 3*time.Second); err != nil {
if err = send(wsconn, head, 3*time.Second); err != nil {
log.Warn("Failed to send initial header to client", "err", err)
return
}
Expand All @@ -372,19 +384,19 @@ func (f *faucet) apiHandler(conn *websocket.Conn) {
Tier uint `json:"tier"`
Captcha string `json:"captcha"`
}
if err = websocket.JSON.Receive(conn, &msg); err != nil {
if err = conn.ReadJSON(&msg); err != nil {
return
}
if !*noauthFlag && !strings.HasPrefix(msg.URL, "https://gist.github.com/") && !strings.HasPrefix(msg.URL, "https://twitter.com/") &&
!strings.HasPrefix(msg.URL, "https://plus.google.com/") && !strings.HasPrefix(msg.URL, "https://www.facebook.com/") {
if err = sendError(conn, errors.New("URL doesn't link to supported services")); err != nil {
if err = sendError(wsconn, errors.New("URL doesn't link to supported services")); err != nil {
log.Warn("Failed to send URL error to client", "err", err)
return
}
continue
}
if msg.Tier >= uint(*tiersFlag) {
if err = sendError(conn, errors.New("Invalid funding tier requested")); err != nil {
if err = sendError(wsconn, errors.New("Invalid funding tier requested")); err != nil {
log.Warn("Failed to send tier error to client", "err", err)
return
}
Expand All @@ -400,7 +412,7 @@ func (f *faucet) apiHandler(conn *websocket.Conn) {

res, err := http.PostForm("https://www.google.com/recaptcha/api/siteverify", form)
if err != nil {
if err = sendError(conn, err); err != nil {
if err = sendError(wsconn, err); err != nil {
log.Warn("Failed to send captcha post error to client", "err", err)
return
}
Expand All @@ -413,15 +425,15 @@ func (f *faucet) apiHandler(conn *websocket.Conn) {
err = json.NewDecoder(res.Body).Decode(&result)
res.Body.Close()
if err != nil {
if err = sendError(conn, err); err != nil {
if err = sendError(wsconn, err); err != nil {
log.Warn("Failed to send captcha decode error to client", "err", err)
return
}
continue
}
if !result.Success {
log.Warn("Captcha verification failed", "err", string(result.Errors))
if err = sendError(conn, errors.New("Beep-bop, you're a robot!")); err != nil {
if err = sendError(wsconn, errors.New("Beep-bop, you're a robot!")); err != nil {
log.Warn("Failed to send captcha failure to client", "err", err)
return
}
Expand All @@ -436,7 +448,7 @@ func (f *faucet) apiHandler(conn *websocket.Conn) {
)
switch {
case strings.HasPrefix(msg.URL, "https://gist.github.com/"):
if err = sendError(conn, errors.New("GitHub authentication discontinued at the official request of GitHub")); err != nil {
if err = sendError(wsconn, errors.New("GitHub authentication discontinued at the official request of GitHub")); err != nil {
log.Warn("Failed to send GitHub deprecation to client", "err", err)
return
}
Expand All @@ -453,7 +465,7 @@ func (f *faucet) apiHandler(conn *websocket.Conn) {
err = errors.New("Something funky happened, please open an issue at https://github.com/XinFinOrg/XDPoSChain/issues")
}
if err != nil {
if err = sendError(conn, err); err != nil {
if err = sendError(wsconn, err); err != nil {
log.Warn("Failed to send prefix error to client", "err", err)
return
}
Expand All @@ -477,7 +489,7 @@ func (f *faucet) apiHandler(conn *websocket.Conn) {
signed, err := f.keystore.SignTx(f.account, tx, f.config.ChainId)
if err != nil {
f.lock.Unlock()
if err = sendError(conn, err); err != nil {
if err = sendError(wsconn, err); err != nil {
log.Warn("Failed to send transaction creation error to client", "err", err)
return
}
Expand All @@ -486,7 +498,7 @@ func (f *faucet) apiHandler(conn *websocket.Conn) {
// Submit the transaction and mark as funded if successful
if err := f.client.SendTransaction(context.Background(), signed); err != nil {
f.lock.Unlock()
if err = sendError(conn, err); err != nil {
if err = sendError(wsconn, err); err != nil {
log.Warn("Failed to send transaction transmission error to client", "err", err)
return
}
Expand All @@ -505,13 +517,13 @@ func (f *faucet) apiHandler(conn *websocket.Conn) {

// Send an error if too frequent funding, othewise a success
if !fund {
if err = sendError(conn, fmt.Errorf("%s left until next allowance", common.PrettyDuration(timeout.Sub(time.Now())))); err != nil { // nolint: gosimple
if err = sendError(wsconn, fmt.Errorf("%s left until next allowance", common.PrettyDuration(timeout.Sub(time.Now())))); err != nil { // nolint: gosimple
log.Warn("Failed to send funding error to client", "err", err)
return
}
continue
}
if err = sendSuccess(conn, fmt.Sprintf("Funding request accepted for %s into %s", username, address.Hex())); err != nil {
if err = sendSuccess(wsconn, fmt.Sprintf("Funding request accepted for %s into %s", username, address.Hex())); err != nil {
log.Warn("Failed to send funding success to client", "err", err)
return
}
Expand Down Expand Up @@ -581,12 +593,12 @@ func (f *faucet) loop() {
"requests": f.reqs,
}, time.Second); err != nil {
log.Warn("Failed to send stats to client", "err", err)
conn.Close()
conn.conn.Close()
continue
}
if err := send(conn, head, time.Second); err != nil {
log.Warn("Failed to send header to client", "err", err)
conn.Close()
conn.conn.Close()
}
}
f.lock.RUnlock()
Expand All @@ -608,7 +620,7 @@ func (f *faucet) loop() {
for _, conn := range f.conns {
if err := send(conn, map[string]interface{}{"requests": f.reqs}, time.Second); err != nil {
log.Warn("Failed to send requests to client", "err", err)
conn.Close()
conn.conn.Close()
}
}
f.lock.RUnlock()
Expand All @@ -618,23 +630,25 @@ func (f *faucet) loop() {

// sends transmits a data packet to the remote end of the websocket, but also
// setting a write deadline to prevent waiting forever on the node.
func send(conn *websocket.Conn, value interface{}, timeout time.Duration) error {
func send(conn *wsConn, value interface{}, timeout time.Duration) error {
if timeout == 0 {
timeout = 60 * time.Second
}
conn.SetWriteDeadline(time.Now().Add(timeout))
return websocket.JSON.Send(conn, value)
conn.wlock.Lock()
defer conn.wlock.Unlock()
conn.conn.SetWriteDeadline(time.Now().Add(timeout))
return conn.conn.WriteJSON(value)
}

// sendError transmits an error to the remote end of the websocket, also setting
// the write deadline to 1 second to prevent waiting forever.
func sendError(conn *websocket.Conn, err error) error {
func sendError(conn *wsConn, err error) error {
return send(conn, map[string]string{"error": err.Error()}, time.Second)
}

// sendSuccess transmits a success message to the remote end of the websocket, also
// setting the write deadline to 1 second to prevent waiting forever.
func sendSuccess(conn *websocket.Conn, msg string) error {
func sendSuccess(conn *wsConn, msg string) error {
return send(conn, map[string]string{"success": msg}, time.Second)
}

Expand Down
4 changes: 2 additions & 2 deletions cmd/puppeth/wizard_genesis.go
Original file line number Diff line number Diff line change
Expand Up @@ -145,8 +145,8 @@ func (w *wizard) makeGenesis() {
genesis.Config.XDPoS.V2.CurrentConfig.TimeoutSyncThreshold = w.readDefaultInt(3)

fmt.Println()
fmt.Printf("How many v2 vote collection to generate a QC, should be two thirds of masternodes? (default = %d)\n", common.MaxMasternodesV2/3*2+1)
genesis.Config.XDPoS.V2.CurrentConfig.CertThreshold = w.readDefaultInt(common.MaxMasternodesV2)/3*2 + 1
fmt.Printf("How many v2 vote collection to generate a QC, should be two thirds of masternodes? (default = %f)\n", 0.666)
genesis.Config.XDPoS.V2.CurrentConfig.CertThreshold = w.readDefaultFloat(0.666)

genesis.Config.XDPoS.V2.AllConfigs[0] = genesis.Config.XDPoS.V2.CurrentConfig

Expand Down
8 changes: 8 additions & 0 deletions cmd/utils/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -406,6 +406,11 @@ var (
Usage: "HTTP-RPC server listening port",
Value: node.DefaultHTTPPort,
}
RPCHttpWriteTimeoutFlag = cli.DurationFlag{
Name: "rpcwritetimeout",
Usage: "HTTP-RPC server write timeout (default = 10s)",
Value: node.DefaultHTTPWriteTimeOut,
}
RPCCORSDomainFlag = cli.StringFlag{
Name: "rpccorsdomain",
Usage: "Comma separated list of domains from which to accept cross origin requests (browser enforced)",
Expand Down Expand Up @@ -735,6 +740,9 @@ func setHTTP(ctx *cli.Context, cfg *node.Config) {
if ctx.GlobalIsSet(RPCPortFlag.Name) {
cfg.HTTPPort = ctx.GlobalInt(RPCPortFlag.Name)
}
if ctx.GlobalIsSet(RPCHttpWriteTimeoutFlag.Name) {
cfg.HTTPWriteTimeout = ctx.GlobalDuration(RPCHttpWriteTimeoutFlag.Name)
}
if ctx.GlobalIsSet(RPCCORSDomainFlag.Name) {
cfg.HTTPCors = splitAndTrim(ctx.GlobalString(RPCCORSDomainFlag.Name))
}
Expand Down
2 changes: 1 addition & 1 deletion common/constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ const (
EpocBlockOpening = 850
EpocBlockRandomize = 900
MaxMasternodes = 18
MaxMasternodesV2 = 108
MaxMasternodesV2 = 108 // Last v1 masternodes
LimitPenaltyEpoch = 4
LimitPenaltyEpochV2 = 0
BlocksPerYearTest = uint64(200000)
Expand Down
2 changes: 1 addition & 1 deletion common/constants/constants.go.devnet
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ const (
EpocBlockOpening = 850
EpocBlockRandomize = 900
MaxMasternodes = 18
MaxMasternodesV2 = 108
MaxMasternodesV2 = 108 // Last v1 masternodes
LimitPenaltyEpoch = 4
LimitPenaltyEpochV2 = 0
BlocksPerYearTest = uint64(200000)
Expand Down
2 changes: 1 addition & 1 deletion common/constants/constants.go.testnet
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ const (
EpocBlockOpening = 850
EpocBlockRandomize = 900
MaxMasternodes = 18
MaxMasternodesV2 = 15
MaxMasternodesV2 = 15 // Last v1 masternodes
LimitPenaltyEpoch = 4
LimitPenaltyEpochV2 = 0
BlocksPerYearTest = uint64(200000)
Expand Down
Loading

0 comments on commit 5a9edbd

Please sign in to comment.